在 Python 爬虫时,在一段时间内请求数量过多,有时由于防爬机制,可能会出现不能继续爬取的问题。解决问题的方法可以是加长请求的间隔,或者从根本上使用动态 IP ,即将大量请求分散到大量的 IP 地址上来请求,从而使防爬机制不会注意。
一个比较好用的高匿名 IP 的网站:http://www.xicidaili.com/nn/
普遍的认识是这样的:
透明代理,即服务器知道请求方的代理 IP 和真实 IP
匿名代理,服务器知道使用了代理,但不知道真实的 IP
高匿代理,服务器不知道使用了代理,也就不会知道真实的 IP
其实使用高匿代理也只是增加了查询的难度,并不是查不到真实 IP 的。
对于爬虫的话,利用大量的高匿 IP ,并且加大请求间隔,是可以不被防爬机制注意的。
我们可以通过简单的代码来取到这个网站的所有 IP 地址来方便使用:
import requests
import random
import re
url = 'http://www.xicidaili.com/nn/'
html = requests.get(url=url, headers=headers).text
regip = r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) \s*?(\d*) '
matcher = re.compile(regip)
ipstr = re.findall(matcher, html)
ip_list = []
for ipport in ipstr:
ip_list.append(ipport[0] + ':' + ipport[1])
# 随机获取列表中一个ip
ip = random.choice(iplist)
或者使用
from bs4 import BeautifulSoup;
import requests
import random
url = 'http://www.xicidaili.com/nn/'
html = requests.get(url=url, headers=headers).text
soup = BeautifulSoup(html, 'lxml')
ips = soup.find(id='ip_list').find_all('tr')
ip_list = []
for i in range(1, len(ips)):
ip_info = ips[i]
tds = ip_info.find_all('td')
ip_list.append(tds[1].text + ':' + tds[2].text)
# 随机获取列表中一个ip
ip = random.choice(iplist)
使用时,可以使用 requests 来添加代理,获取响应:
response = requests.get(url, proxies={"http" : proxy}, timeout=10)
return response.content
或者使用 ProxyHandler :
httpproxy_handler = urllib.ProxyHandler({"http" : proxy})
opener = urllib.build_opener(httpproxy_handler)
request = urllib.Request(image)
opener.addheaders = headers;
response = opener.open(request, timeout=10)
另外,在使用动态 IP 的同时,可以使用动态 Header ,比如可以这样定好一个 header 的列表,每次请求 header 也随机取:
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
"Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
"Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
"Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
"Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5"]
headers = [('User-Agent', random.choice(USER_AGENTS)), ("Upgrade-Insecure-Requests", "1"),
("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"),
("Accept-Encoding", "gzip, deflate, sdch"),
("Accept-Language", "zh-CN,zh;q=0.8,en;q=0.6"),
("Cache-Control", "no-cache")]
'''
或者:
注意有时使用的组件不同header的写法格式也有区别
self.headers = {'User-Agent': self.user_agent, "Upgrade-Insecure-Requests": "1",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, sdch",
"Accept-Language": "zh-CN,zh;q=0.8,en;q=0.6",
"Cache-Control": "no-cache"}
'''