目录
前面我们讲到一些服务器会检查收到的请求头从而判断访问网站的是否是爬虫,这一节我们就来讲讲具体如何编写请求头从而达到通过服务器检查的目的。
User-Agent
文题中的Request指的是Http请求。Request由请求行、请求头和请求体组成(GET的请求体为空)。对于大多数情况下是采用GET请求的爬虫而言,模仿浏览器至关重要的一步就是编造好一个请求头。(如果你要伪造POST请求提交表单就需要做好模仿浏览器的滑动点击等动作的准备了,当然要爬取带有ajax的网站即使是GET也要如此)
Urllib直接向浏览器发送请求的请求头UA(User-Agent)通常会注明为“Python-Urllib”,这相当于直接告诉了服务器你是爬虫。并且,相当多的服务器会检查请求的UA。所以如果我们要伪装请求,第一步就是重写一个“看上去正常”的UA头。
fake-useragent伪造UA
不得不说Python的一大优点确实就是第三方库多的令人发指,而且几乎是想要啥就有啥。同行前辈们这么努力,经常让我这种后生有一种出生已经输了的感觉哈。
回归主题,UA的定义上一节我已经写了,这里就不赘述。Python有个库fake-useragent可以随机出一系列UA。以下是实例:
from fake_useragent import UserAgent
for i in range(1,3):
print(UserAgent().random)
其输出为:
Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1664.3 Safari/537.36
Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36 Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10
只要声明一个UserAgent类的对象就可以通过其random属性获取一个随机的UA头。事实上你也不需要像我一样每次都使用一个新的UserAgent对象,因为同一个UserAgent对象每次访问random时都会产生一个新的随机UA。
fake-useragent使用中的小问题
有时候使用fake-useragent时会报错fake_useragent.errors.FakeUserAgentError: Maximum amount of retries reached,解决方案有两个:
-使用pip install -U fake-useragent 命令升级fake-useragent。
-在创建UserAgent对象时加上use_cache_server=False。
Referer
上一节里我提到过有些网站也会验证请求的Referer,这主要是为了防止盗链和恶意请求。
Referer的定义(找不到官方定义我就自己写了一个)
Referer指向的是“带你来到这个链接的链接”,也就是你的上一个链接。比如说你从4399的首页点进了一个广告,那么你访问这个广告的链接的Referer就是“www.4399.com”。
注:听说Referer本来是Referrer,不过是为了兼容性才将错就错,不知真假,当个趣闻吧。
仿造Referer
这个肯定要具体情况具体分析,根据情况手动设置。毕竟让爬虫自己找出上一级页面是不可能的事情(别说爬虫了,你上你也不行啊(笑))。在这里特别讲一下Referer只是为了提醒读者还会存在这种可能需要注意。
还有一个需要注意的地方,Referer也不是不能为空,比如在浏览器输入框里直接输入网址访问的情况就没有Referer。
让爬虫带上自己编写的Header
urllib2与requests的例子如下:
from urllib.request import *
header={"User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.90 Safari/537.36"}
request=Request("https://www.baidu.com",headers=header) #要带上headers就要使用一个Request对象把url与headers组织到一起
response=urlopen(request)
print(response.read().decode("utf-8"))
import requests
header={"UserAgent":"Mozilla/5.0 (Windows NT 6.1; U; de; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 11.01"}
response=requests.get("http://www.baidu.com",headers=header)
response.encoding="utf-8"
print(response.text)