百度百科对User Agent的摘要:
User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
我们访问一个网站获取它的返回内容,可以通过Chrome、Firefox和IE等,或者我们写一段代码获取。
实际上我们的浏览器只是一个代理,服务器有时候需要知道是什么浏览器访问的,就需要写一段字符串来表明。也就是说User Agent是起标识作用的。
User Agent是放在请求头中的。这是浏览器自动加的,同一个浏览器,内容其实是一样的。
在进行修改之前,进行调试,在response中的request变量中的headers中,有一个User-Agent变量,它的值为:
想要实现随机切换User Agent十分简单,可以在settings.py中增一个user_agent_list变量:
user_agent_list = [
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
'Mozilla/5.0 (Windows NT 6.1; W…) Gecko/20100101 Firefox/68.0',
]
然后在cnblogs.py中引入它:
from Spider.settings import user_agent_list
为了实现随机选择User Agent,引入:
import random
新建类变量:
headers = {
'HOST': "news.cnblogs.com",
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; W…) Gecko/20100101 Firefox/68.0',
'referer': 'https://news.cnblogs.com/'
}
通过下面三句,就可以获得一个有随机User Agent的headers了:
random_index = random.randint(0, len(user_agent_list)-1)
random_agent = user_agent_list[random_index]
self.headers["User-Agent"] = random_agent
并在yield出去的Request对象中添加:
headers=headers
上面生成随机agent的的逻辑应该放在一个Request被yield出去之前,而headers变量应该放在类中。
接下来,request中的headers下的user agent会在下面二者中随机出现:
这样做有一个问题,需要我们在每一处Request被yield出去之前都加上那三条逻辑。
删除或注释除了settings中配置user_agent_list以外的的代码。
于是我们使用download middleware完成这项任务,先复习架构:
我们首先将settings.py中关于DOWNLOADER_MIDDLEWARES的注释取消:
DOWNLOADER_MIDDLEWARES = {
'Spider.middlewares.SpiderDownloaderMiddleware': 543,
}
我们看看默认提供的一个UserAgentMiddleware:
刚刚默认的user-agent就是在这里设置的。
读代码,可以知道,如果settings.py中设置了USER_AGENT,就不会使用默认的Scrapy,所以可以在settings.py中加入:
# 默认的User Agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; W…) Gecko/20100101 Firefox/68.0'
看这个也行,其实生成项目时,自动生成的middleware.py中的示例代码也交代了如何写middleware,比较重要的方法是process_request,所有对Request的处理都在这儿。
官网上说,downloader middleware是在request与response处理中的钩子框架,就是说它可以hook住一些函数,只要实现了这个函数的类,都可以被执行。用以全局修改Request和Response。
官网上还说,如果我们自己实现了UserAgentMiddleware,就必须把默认提供的设置为None,或者你可以把自己配置的middleware的数字设的大一点,这样就可以最后处理。下面把它置为None:
DOWNLOADER_MIDDLEWARES = {
'Spider.middlewares.SpiderDownloaderMiddleware': 543,
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None
}
在middlewares.py中实现自己的middleware:
import random
from Spider.settings import user_agent_list
class RandomUserAgentMiddlware(object):
"""
随机更换user-agent
"""
def __init__(self, crawler):
super(RandomUserAgentMiddlware, self).__init__()
self.user_agent_list = crawler.settings.get("user_agent_list", [])
@classmethod
def from_crawler(cls, crawler):
return cls(crawler)
def process_request(self, request, spider):
def rdm():
# 获取一个随机的user agent
random_index = random.randint(0, len(user_agent_list) - 1)
random_agent = user_agent_list[random_index]
return random_agent
request.headers.setdefault('User-Agent', rdm())
(函数中定义函数,是动态语言闭包的一种特性)
配置它:
DOWNLOADER_MIDDLEWARES = {
'Spider.middlewares.SpiderDownloaderMiddleware': 543,
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
'Spider.middlewares.RandomUserAgentMiddlware': 600,
}
调试,果然可以。
但我们不这样做,因为这样做的话,user_agent_list是写死了的。把user_agent_list也注释掉。
github上搜索:
fake-useragent
直达:https://github.com/hellysmile/fake-useragent
我们先安装:
pip install fake-useragent
用法也很简单,我们可以在命令行中测试。
>>> from fake_useragent import UserAgent
>>> ua = UserAgent()
>>> ua.ie
'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC
6.0; Zune 4.0; Tablet PC 2.0; InfoPath.3; .NET4.0C; .NET4.0E)'
>>> ua.ie
'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) chromeframe/10.0.648.205'
>>> ua.chrome
'Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36'
>>> ua.chrome
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'
>>> ua.random
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17'
>>> ua.random
'Mozilla/5.0 (Windows NT 6.1; rv:27.3) Gecko/20130101 Firefox/27.3'
这个包实际上是维护了一个url。这个url会更新,使得老版本的url不能使用,所以需要我们维护。
更改之前的middleware:
from fake_useragent import UserAgent
class RandomUserAgentMiddlware(object):
"""
随机更换user-agent
"""
def __init__(self, crawler):
super(RandomUserAgentMiddlware, self).__init__()
self.ua = UserAgent()
@classmethod
def from_crawler(cls, crawler):
return cls(crawler)
def process_request(self, request, spider):
request.headers.setdefault('User-Agent', self.ua.random)
为了让这个middleware能根据我们的配置进行随机选择,我们在settings中加入一个配置:
# 随机user agent 类型
RANDOM_UA_TYPE = 'random'
并进一步更改middleware:
class RandomUserAgentMiddlware(object):
"""
随机更换user-agent
"""
def __init__(self, crawler):
super(RandomUserAgentMiddlware, self).__init__()
self.ua = UserAgent()
self.ua_type = crawler.settings.get("RANDOM_UA_TYPE", "random")
@classmethod
def from_crawler(cls, crawler):
return cls(crawler)
def process_request(self, request, spider):
def get_ua():
return getattr(self.ua, self.ua_type)
request.headers.setdefault('User-Agent', get_ua())
有其他配置,就按照这种模式来。