常见反爬虫机制与应对方法

前言

爬虫的目的就是大规模地、长时间地获取数据,跟我们正常浏览器获取数据相比,虽然机理相差不大,但总是一个IP去爬网站,大规模集中对服务器访问,时间一长就有可能被拒绝。当下,各网站的反爬机制也变得无处不在。只要是个网站,基本都有针对爬虫的手段。然而攻永远比防要容易,所谓道高一尺,魔高一丈。

一、设置下载等待时间/下载频率

大多数情况下,我们遇到的是访问频率限制。如果你访问太快了,网站就会认为你不是一个人。这种情况下需要设定好频率的阈值,否则有可能误伤。

遇到这种网页,最直接的办法是限制访问时间。例如每隔5秒钟访问一次页面。但是如果遇到聪明一点的网站,它检测到你的访问时间,这个人访问了几十个页面,但是每次访问都刚好5秒钟,人怎么可能做到这么准确的时间间隔?肯定是爬虫,被封也是理所当然的!所以访问时间间隔你可以设定为一个随机值,例如0到10之间的随机秒数。

  • 如果是requests进行爬虫,那么我们可以在请求页面之前设置等待时间time.sleep(random.randint(0,10))
  • 如果是scrapy进行爬虫,专门有参数可以设置下载等待时间,这个参数可以设置在setting.py->download_delay里,也可以设置在spider里。

二、修改User-Agent

当我们使用浏览器访问网站的时候,浏览器会发送一小段信息给网站,我们称为Request Headers,在这个头部信息里面包含了本次访问的一些信息,例如编码方式,当前地址,将要访问的地址等等。这些信息一般来说是不必要的,但是现在很多网站会把这些信息利用起来。其中最常被用到的一个信息,叫做“User-Agent”。网站可以通过User-Agent来判断用户是使用什么浏览器访问。不同浏览器的User-Agent是不一样的,但都有遵循一定的规则。

例如,我们在Windows上面的Chrome浏览器,它的User-Agent是:

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36

但是如果我们使用Python的Requests直接访问网站,那么除了网址不提供其他的任何信息,网站收到的User-Agent是空。这个时候网站就知道我们不是使用浏览器访问的,于是它就可以拒绝我们的访问。

最常用的方法就是伪装浏览器,修改User-Agent(用户代理)。 具体方法为把User-Agent的值改为浏览器,甚至可以设置一个User-Agent池(list,数组,字典都可以),存放多个“浏览器”,每次爬取的时候随机取一个来设置User-Agent,这样User-Agent会一直在变化。

常用User-Agent如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
User-Agent = [
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0",
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
"Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
]

  • 进行requests爬虫时,可以将User-Agent放在requests.get()中的headers参数里,具体用法为requests.get(url,headers={‘User-Agent’:’xxx’})
  • 进行scrapy爬虫时,可以通过下载中间件middlewares.py进行设置。

三、设置代理IP

如果对页的爬虫的效率有要求,那就不能通过设定访问时间间隔的方法来绕过频率检查了。

代理IP访问可以解决这个问题。如果用100个代理IP访问100个页面,可以给网站造成一种有100个人,每个人访问了1页的错觉。这样自然而然就不会限制你的访问了。

代理IP经常会出现不稳定的情况。你随便搜一个“免费代理”,会出现很多网站,每个网站也会给你很多的代理IP,但实际上,真正可用的代理IP并不多。你需要维护一个可用的代理IP池,但是一个免费的代理IP,也许在你测试的时候是可以使用的,但是几分钟以后就失效了。使用免费代理IP是已经费时费力,而且很考验你运气的事情。

  • 进行requests爬虫时,可以在requests.get()中的proxies参数里设置代理ip,具体方法如下:requests.get(url,proxies={“http”:”ip:port”})
  • 进行scrapy爬虫时,可以通过下载中间件middlewares.py进行设置代理ip。

下面是我爬取快代理免费的代理IP脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import requests
from bs4 import BeautifulSoup
import logging
import sys
import random

def obtainProxy(UA):
httpList = []
url = 'https://www.kuaidaili.com/free/inha/'
for i in range(1,15):
try:
r = requests.get(url+str(i),headers={'User-Agent':random.choice(UA)})
except:
logger = logging.basicConfig(level=logging.INFO, format ='%(asctime)s - %(levelname)s - %(message)s')
logger.error('Url cannot be requested normally.')
sys.exit(0)
else:
bsp = BeautifulSoup(r.text,"lxml")
proxyList = bsp.find("table",{"class":"table table-bordered table-striped"})
if proxyList != None:
proxyList = proxyList.findAll("tr")[1:]
for proxy in proxyList:
form = "%s://%s:%s"
tdList = proxy.findAll("td")
httpList.append(form % (tdList[3].string.lower(),tdList[0].string,tdList[1].string))

return httpList

def checkProxy(UA):
validHttpList = obtainProxy(UA)
url = "https://www.baidu.com"
for http in range(len(validHttpList)):
try:
r = requests.get(url,headers={'User-Agent':random.choice(UA)},proxies={"http":validHttpList[http]},timeout=5)
if r.status_code != 200:
del validHttpList[http]
except Exception as e:
print(e)

return validHttpList

if __name__ == '__main__':
UserAgent = [
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0",
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
"Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
]
httpList = checkProxy(UserAgent)
print("http:\n"+'*'*40)
for proxy in httpList:
print(proxy)
print('*'*40)

运行结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
http:
****************************************
http://111.77.197.22:9999
http://113.128.8.62:9999
http://123.55.114.160:9999
http://58.55.202.93:9999
http://125.123.142.195:9999
http://117.42.200.143:9999
http://183.158.206.127:9000
http://114.235.23.78:9000
http://120.83.103.145:9999
http://116.209.55.248:9999
http://60.188.60.29:9000
http://113.121.147.9:9999
http://144.255.14.7:9999
http://121.233.251.147:9999
http://117.41.38.19:9000
http://163.125.28.220:8118
http://117.42.202.17:9999
http://1.192.242.164:9999
http://117.90.252.85:9000
http://117.42.200.158:9999
http://163.204.245.130:9999
http://49.81.125.105:9000
http://60.184.194.157:3128
http://113.121.145.218:9999
http://47.107.190.212:8118
http://111.177.163.12:9999
http://180.118.86.142:9000
http://115.193.97.67:9000
http://60.182.21.88:9000
http://60.191.57.79:10010
http://115.223.253.196:9000
http://121.225.26.246:3128
http://121.232.199.222:9000
http://120.77.247.147:80
http://116.209.62.21:9999
http://117.87.177.207:9000
http://123.163.118.236:9999
http://121.233.251.206:9999
http://163.204.241.70:9999
http://182.111.64.7:36323
http://123.115.131.159:8060
http://114.234.80.97:9000
http://124.94.195.223:9999
http://49.70.33.206:9999
http://117.42.201.96:9999
****************************************

四、设置cookies

cookie其实是储存在用户终端的一些被加密的数据,有些网站通过cookies来识别用户身份,如果某个访问总是高频率地发请求,很可能会被网站注意到,被嫌疑为爬虫,这时网站就可以通过cookie找到这个访问的用户而拒绝其访问。
可以自定义设置cookie策略(防止cookie rejected问题:拒绝写入cookie)或者禁止cookies。

1.自定义设置cookies策略(防止cookierejected问题,拒绝写入cookie)

详见官方文档: http://hc.apache.org/httpcomponents-client-4.3.x/tutorial/html/statemgmt.html#d5e553

2.禁止cookies

通过禁止cookie,这是客户端主动阻止服务器写入。禁止cookie可以防止可能使用cookies识别爬虫的网站来ban掉我们。
在scrapy爬虫中可以设置COOKIES_ENABLES= FALSE,即不启用cookies middleware,不向web server发送cookies。

参考链接: https://blog.csdn.net/wbcg111/article/details/53572644

五、分布式爬取