爬虫与反爬:使用用户代理User-agent
网页抓取机器人容易被服务器识别并拒绝提供服务,通过网页请求指定用户代理User-agent为浏览器,将爬虫伪装成浏览器访问,从而提升爬取成功率。
1. 用户代理User-Agent
客户端向服务器请求一张页面时,可以额外附上一些自己的信息(如使用什么操作系统、什么浏览器),以便让服务器提供更好的服务
request-header = Accept ; Section 14.1
| Accept-Charset ; Section 14.2
| Accept-Encoding ; Section 14.3
| Accept-Language ; Section 14.4
| Authorization ; Section 14.8
| Expect ; Section 14.20
| From ; Section 14.22
| Host ; Section 14.23
| If-Match ; Section 14.24
| If-Modified-Since ; Section 14.25
| If-None-Match ; Section 14.26
| If-Range ; Section 14.27
| If-Unmodified-Since ; Section 14.28
| Max-Forwards ; Section 14.31
| Proxy-Authorization ; Section 14.34
| Range ; Section 14.35
| Referer ; Section 14.36
| TE ; Section 14.39
| User-Agent ; Section 14.43
最后一项User-Agent用户代理包含一个特有字符串(characteristic string),指明自己应用类型、操作系统、软件版本。用requests库爬取,以我为例,会发送如下请求头:
Host: httpbin.org
User-Agent: python-requests/2.24.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
这里用户代理是python-requests
(若用urllib标准库,则用户代理为python-urllib
),典型的网页爬虫,容易被服务器识别并拒绝提供服务。
2. 浏览器User agent
用户代理可以是网页抓取机器人、下载管理器、浏览器或可以访问Web的其他应用程序。解决上述问题,可以将用户代理改为浏览器,即爬虫行为伪装成正常的浏览器访问。
获取Chrome浏览器的User-Agent,在地址栏输入chrome://version
,回车就能看到User Agent,以我为例:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36
将User-Agent
作为header
字典的一对健值传给requests.get(url, params=None, **kwargs),如下:
#!/usr/bin/env python3
from bs4 import BeautifulSoup
url = 'https://zozo.jp/shop/auntierosa/goods/50202474/?did=81429464&rid=1068'
headers = {'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36"}
# requests
import requests
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'lxml')
# urllib
from urllib.request import Request, urlopen
req = Request(url, headers=headers)
f = urlopen(req)
soup = BeautifulSoup(f, 'lxml')
试想通过相同的浏览器非常频繁被访问同一个站,这很容易被服务器识别为爬虫程序。基于这样的观察,PC通常装了多个浏览器,因此可以轮流或者随机使用浏览器来访问,即轮流或者随机使用多个User agent。
3. 随机使用User agent
幸运的是,已经有现成的Python模块提供该功能,fake-useragent。
运行命令pip3 install fake-useragent
安装fake-useragent
。使用起来也很简单,举例如下:
from bs4 import BeautifulSoup
import requests
from fake_useragent import UserAgent
ua = UserAgent()
ua.update() # 更新用户代理列表
headers = {'User-Agent': ua.random}
response = requests.get('http://sparkandshine.net', headers=headers)
soup = BeautifulSoup(response.text, 'lxml')
值得注意的是,fake-useragent
将用户代理列表存储在本地机器,因此在使用过程,需要更新,否则会报fake_useragent.errors.FakeUserAgentError: Maximum amount of retries reached
错误。
- 方法1:运行命令
pip3 install -U fake-useragent
- 方法2:在代码中,加入
ua.update()
但这依然容易被服务器识别到,因为所有访问都来自同一个IP地址,解决该问题,可以使用IP代理。
参考资料:
[1] RFC 2616 -- HTTP/1.1: 14.43 User-Agent
[2] How can I see the entire HTTP request that's being sent by my Python application?