Scrapy使用随机User-Agent爬取网站

简介: 小哈.jpg在爬虫爬取过程中,我们常常会使用各种各样的伪装来降低被目标网站反爬的概率,其中随机更换User-Agent就是一种手段。在scrapy中,其实已经内置了User-Agent中间件,class UserAgentMiddl...
img_bfc63943164d22241520493724e082d9.jpe
小哈.jpg

在爬虫爬取过程中,我们常常会使用各种各样的伪装来降低被目标网站反爬的概率,其中随机更换User-Agent就是一种手段。
在scrapy中,其实已经内置了User-Agent中间件,

class UserAgentMiddleware(object):
    """This middleware allows spiders to override the user_agent"""

    def __init__(self, user_agent='Scrapy'):
        self.user_agent = user_agent

    @classmethod
    def from_crawler(cls, crawler):
        o = cls(crawler.settings['USER_AGENT'])
        crawler.signals.connect(o.spider_opened, signal=signals.spider_opened)
        return o

    def spider_opened(self, spider):
        self.user_agent = getattr(spider, 'user_agent', self.user_agent)

    def process_request(self, request, spider):
        if self.user_agent:
            request.headers.setdefault(b'User-Agent', self.user_agent)

上图是scrapy自带的UserAgentMiddleware中间件,通过代码可以发现,如果我们没有在setting配置文件中设置headers的User-Agent,scrapy会把User-Agent设置为"Scrapy"。

原理

当我们通过 spider yield 一个 request 的时候,首先通过 spider middlewares 到达 scrapy engine,然后 engine 将 request 放到 scheduler 的队列中,通过 scheduler 调度队列中的 request ,scheduler 选中一个 request 后,将 request 通过 engine 传递给 downloader,在这之前,必然会经过 downloader middlewares,downloader 下载好之后,将 response 返回给 engine,engine 在将 response 返回给 spider,我们就可以在 spider 中调用 callback 进行解析,简单的流程大概就是这样。

那么,我们在将 request 提交给 downloader 进行下载之前,就需要将 User-Agent 进行变化,也就是每次都需要随机取一个 User-Agent 提交到 downloader 进行下载。在提交到 downloader 的时候,必然会经过 downloader middlewares,所以我们实现随机获取 User-Agent 的逻辑部分,可以在 downloader midllewares 这里实现。

第一种方法

可以把多个User-Agent作为一个配置在setting文件中

user_agent_list = [
    "ua1",
    "ua2",
    "ua3",
]

然后再编写downloader midllewares

class RandomUserAgentMiddleware(object):
    def __init__(self, crawler):
        super(RandomUserAgentMiddleware, self).__init__()
        self.user_agent_list = crawler.get("user_agent_list", [])

    @classmethod
    def from_crawler(cls, crawler):
        return cls(crawler)

    def process_request(self, request, spider):
        #无效的方法
        request.headers.setdefault("User-Agent", random.choice(self.user_agent_list))
        #有效的方法
        request.headers['User-Agent'] = random.choice(self.user_agent_list)
注意:

上图代码在process_request方法中写了两种设置User-Agent的方法,其中上边那种方法经过测试是结果是无效的,所以采用下边那种方法。因为setdefault这个方法是:如果没有User-Agent 这个键才会设置User-Agent并把User-Agent的value设置为random.choice(self.user_agent_list),但其实代码运行到这里时,User-Agent 这个键是存在的,所以使用setdefault不会生效。如果这边有疑问可以评论提问我。

补充更正:

上边说的 代码在process_request方法中写了两种设置User-Agent的方法,其实都可以,之前之所以上边那行不能实现是因为我在setting中把scrapy自带的UserAgentMiddleware取消没有成功,原因是路径写错了,现给出正确配置方法:

DOWNLOADER_MIDDLEWARES = {
    'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware': None,
    'crawl_spider.middlewares.RandomUserAgentMiddleware': 543,
}

先把scrapy自带的UserAgentMiddleware置为None,再增加我们自己写的中间件便可,

这样做可以实现切换User-Agent的功能,但是第一需要自己维护一个大的User-Agent list在配置文件中,第二就是有局限性,毕竟维护的User-Agent不会有那么的大而全,所以这里介绍另一种方法。

第二种方法(推荐)

fake-useragent 这个库提供了我们随机选择useragent的功能。
感兴趣的同学可以深入研究下源码,源码很简单,这里只介绍怎么在scrapy中使用它。
话不多说上代码

class RandomUserAgentMiddleware(object):
    def __init__(self, crawler):
        super(RandomUserAgentMiddleware, 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['User-Agent'] = get_ua()

首先我们在setting配置文件中设置一个变量RANDOM_UA_TYPE,它的功能是可以按照我们自己配置的值来选择useragent。

# 随机选择UA
RANDOM_UA_TYPE = "random"
# 只选择ie的UA
RANDOM_UA_TYPE = "ie"

当然了,最终我们还要把我们的RandomUserAgentMiddleware中间件配置到setting中:

DOWNLOADER_MIDDLEWARES = {
    'crawl_spider.middlewares.RandomUserAgentMiddleware': 543,
}

至此,完成了scrapy加随机User-Agent的需求。

目录
相关文章
|
7月前
|
数据采集 中间件 Python
Scrapy爬虫:利用代理服务器爬取热门网站数据
Scrapy爬虫:利用代理服务器爬取热门网站数据
|
3月前
|
安全
利用迅雷和MS06014漏洞传播Worm.Win32.Agent.a的电子书网站
利用迅雷和MS06014漏洞传播Worm.Win32.Agent.a的电子书网站
|
3月前
|
JavaScript 前端开发 数据安全/隐私保护
一个会下载 Trojan.DL.Agent.wzr 的政府网站
一个会下载 Trojan.DL.Agent.wzr 的政府网站
一个传播Trojan.Win32.Agent.aac的网站
一个传播Trojan.Win32.Agent.aac的网站
|
5月前
|
数据采集 存储 缓存
使用Scrapy进行网络爬取时的缓存策略与User-Agent管理
使用Scrapy进行网络爬取时的缓存策略与User-Agent管理
|
6月前
|
Web App开发 iOS开发 Python
经验大分享:scrapy框架爬取糗妹妹网站qiumeimei.com图片
经验大分享:scrapy框架爬取糗妹妹网站qiumeimei.com图片
42 0
|
XML 数据采集 JSON
scrapy_selenium爬取Ajax、JSON、XML网页:豆瓣电影
在网络爬虫的开发过程中,我们经常会遇到一些动态加载的网页,它们的数据不是直接嵌入在HTML中,而是通过Ajax、JSON、XML等方式异步获取的。这些网页对于传统的scrapy爬虫来说,是很难直接解析的。那么,我们该如何使用scrapy_selenium来爬取这些数据格式的网页呢?本文将为你介绍scrapy_selenium的基本原理和使用方法,并给出一个实际的案例。
116 0
|
7月前
|
数据采集 JavaScript 开发者
使用Scrapy有效爬取某书广告详细过程
使用Scrapy有效爬取某书广告详细过程
使用Scrapy有效爬取某书广告详细过程
|
7月前
|
数据采集 Python
Scrapy框架 -- 深度爬取并持久化保存图片
Scrapy框架 -- 深度爬取并持久化保存图片
136 0
|
数据采集 XML 存储
构建一个简单的电影信息爬虫项目:使用Scrapy从豆瓣电影网站爬取数据
这个案例展示了如何使用 Scrapy 框架构建一个简单的爬虫项目,从网页中提取数据并保存到文件中。通过配置、编写爬虫代码、定义数据模型和数据处理管道,你可以灵活地构建各种爬虫应用。
325 0
构建一个简单的电影信息爬虫项目:使用Scrapy从豆瓣电影网站爬取数据
下一篇
DataWorks