文章目录
网站为了避免爬虫采集数据可能会采取一些反爬虫的措施,例如服务器会检测某个 IP 在单位时间内的请求次数,如果这个次数超过了指定的阈值,就直接拒绝服务器,并返回一些错误信息,这种情况称为 封IP;
封IP 的流程是:开始可以正常运行,正常爬取数据,一段时间过后出现错误,比如返回 403 Forbidden,这时打开网页,可能会看到 “您的 IP 访问频率太高” 这样的提示,或者跳出一个验证码让我们识别,通过之后才可以正常访问,但是过一会儿又会变成这样;
代理通过将 IP 伪装起来,让服务器识别不出是由我们本机发起的请求,就可以成功防止封 IP了;
一、代理的设置
代理是 IP 地址和端口的组合,格式是 <ip>:<port>
,如果代理需要访问认证,则还需要额外的用户名和密码两个信息;
1.1 urllib 的代理设置
首先我们以最基础的 urllib 为例,来看一下代理的设置方法,代码如下:
from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener
proxy = '127.0.0.1:9743'
proxy_handler = ProxyHandler({
'http': 'http://' + proxy,
'https': 'https://' + proxy
})
opener = build_opener(proxy_handler)
try:
response = opener.open('http://httpbin.org/get')
print(response.read().decode('utf-8'))
except URLError as e:
print(e.reason)
运行结果如下:
{
"args": {
},
"headers": {
"Accept-Encoding": "identity",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "Python-urllib/3.6"
},
"origin": "106.185.45.153",
"url": "http://httpbin.org/get"
}
这里我们需要借助 ProxyHandler 设置代理,参数是字典类型,键名为协议类型,键值是代理。注意,此处代理前面需要加上协议,即 http 或者 https。当请求的链接是 http 协议的时候,ProxyHandler 会调用 http 代理。当请求的链接是 https 协议的时候,会调用 https 代理。此处生效的代理是:http://127.0.0.1:9743。
创建完 ProxyHandler 对象之后,我们需要利用 build_opener 方法传入该对象来创建一个 Opener,这样就相当于此 Opener 已经设置好代理了。接下来直接调用 Opener 对象的 open 方法,即可访问我们所想要的链接。
运行输出结果是一个 JSON,它有一个字段 origin,标明了客户端的 IP。验证一下,此处的 IP 确实为代理的 IP,并不是真实的 IP。这样我们就成功设置好代理,并可以隐藏真实 IP 了。
如果遇到需要认证的代理,我们可以用如下的方法设置:
from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener
proxy = 'username:password@127.0.0.1:9743'
proxy_handler = ProxyHandler({
'http': 'http://' + proxy,
'https': 'https://' + proxy
})
opener = build_opener(proxy_handler)
try:
response = opener.open('http://httpbin.org/get')
print(response.read().decode('utf-8'))
except URLError as e:
print(e.reason)
这里改变的只是 proxy 变量,只需要在代理前面加入代理认证的用户名密码即可,其中 username 就是用户名,password 为密码,例如 username 为 foo,密码为 bar,那么代理就是 foo:bar@127.0.0.1:9743。
如果代理是 SOCKS5 类型,那么可以用如下方式设置代理:
import socks
import socket
from urllib import request
from urllib.error import URLError
socks.set_default_proxy(socks.SOCKS5, '127.0.0.1', 9742)
socket.socket = socks.socksocket
try:
response = request.urlopen('http://httpbin.org/get')
print(response.read()