爬虫与反爬:使用用户代理User-agent

网页抓取机器人容易被服务器识别并拒绝提供服务,通过网页请求指定用户代理User-agent为浏览器,将爬虫伪装成浏览器访问,从而提升爬取成功率。

1. 用户代理User-Agent

客户端向服务器请求一张页面时,可以额外附上一些自己的信息(如使用什么操作系统、什么浏览器),以便让服务器提供更好的服务[1](如根据不同设备返回不同的页面)。额外附上的信息叫请求头(HTTP Header, request header),有这么多内容:

   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?

[3] HTTP headers – HTTP | MDN

Leave a Reply

Your email address will not be published. Required fields are marked *