Scrapy爬虫——Selenium集成到scrapy

作者: youyuge | 来源:发表于2017-10-03 22:26 被阅读364次

有条件的请支持慕课实战正版课程,本blog仅仅是归纳总结,自用。

理论上,控制流量,selenium完全模拟人类操作,是不会被反扒的,集成到scrapy之后,将大大发挥其作用。

一、准备知识

  1. selenium官方英文document

  2. scrapy v1.0有关下载中间件的中文文档,有条件的可选英文

二、自定义中间件

  • 注意这里的自定义中间件是downloader Middleware下载中间件,位于enginedownloader之间,为了方便我们选用edge浏览器做测试,其他selenium浏览器请参考官方文档:
from selenium import webdriver
from scrapy.http import HtmlResponse

class JSPageMiddleware(object):
    # 通过edge请求动态网页,代替scrapy的downloader
    def process_request(self, request, spider):
        if spider.name == "jobbole":
            browser = webdriver.Edge(
                executable_path='F:/PythonProjects/Scrapy_Job/JobSpider/tools/MicrosoftWebDriver.exe')
            browser.get(request.url)
            import time
            time.sleep(3)
            print ("访问:{0}".format(request.url))

            #直接返回给spider,而非再传给downloader
            return HtmlResponse(url=browser.current_url, body=browser.page_source, encoding="utf-8",
                                request=request)
  • 但是每次请求网页都会新建一个浏览器,然后它会自动关闭,也太费时费力了。我们可以将它作为一个全局变量,在类初始化的时候初始化它,节约内存。我们重写init函数后:
from selenium import webdriver
from scrapy.http import HtmlResponse

class JSPageMiddleware(object):

    def __init__(self):
        self.browser = webdriver.Edge(
                executable_path='F:/PythonProjects/Scrapy_Job/JobSpider/tools/MicrosoftWebDriver.exe')
        super(JSPageMiddleware,self).__init__()

    # 通过edge请求动态网页,代替scrapy的downloader
    def process_request(self, request, spider):
        #判断该spider是否为我们的目标
        if spider.name == "jobbole":
            # browser = webdriver.Edge(
            #     executable_path='F:/PythonProjects/Scrapy_Job/JobSpider/tools/MicrosoftWebDriver.exe')
            self.browser.get(request.url)
            import time
            time.sleep(3)
            print ("访问:{0}".format(request.url))

            #直接返回给spider,而非再传给downloader
            return HtmlResponse(url=self.browser.current_url, body=self.browser.page_source, encoding="utf-8",
                                request=request)
  • 现在,我们只会开启一个浏览器,省时省力!但是,又有一个问题,spider closed的时候,浏览器并不会自动关闭,因为我们的中间件middleware里只有process_request函数,只能处理过程。这就涉及到了scrapy的另一个知识点。

  • 我们发现process_request函数的参数中有spider,那我们可以把浏览器的初始化放入单独的spider里啊,这样就可以做到带seleniumspider的不带的分别管理,并且能多spider开启多个browser

  • 最终版的中间件:

from scrapy.http import HtmlResponse

class JSPageMiddleware(object):

    # 通过edge请求动态网页,代替scrapy的downloader
    def process_request(self, request, spider):
        #判断该spider是否为我们的目标
        if spider.browser:
            # browser = webdriver.Edge(
            #     executable_path='F:/PythonProjects/Scrapy_Job/JobSpider/tools/MicrosoftWebDriver.exe')
            spider.browser.get(request.url)
            import time
            time.sleep(3)
            print ("访问:{0}".format(request.url))

            #直接返回给spider,而非再传给downloader
            return HtmlResponse(url=spider.browser.current_url, body=spider.browser.page_source, encoding="utf-8",
                                request=request)
  • Spider类中加入以下2个函数,其中涉及到了信号量绑定的知识,和Django中是类似的,因为毕竟scrapy借鉴的就是Django
    def __init__(self):
        from selenium import webdriver

        self.browser = webdriver.Edge(
            executable_path='F:/PythonProjects/Scrapy_Job/JobSpider/tools/MicrosoftWebDriver.exe')
        super(JobboleSpider, self).__init__()

        from scrapy.xlib.pydispatch import dispatcher
        from scrapy import signals
        
        # 绑定信号量,当spider关闭时调用我们的函数
        dispatcher.connect(self.spider_closed, signals.spider_closed)

    def spider_closed(self, spider):
        print 'spider closed'
        self.browser.quit()
  • 最后,当然别忘了在settings文件中配置我们的下载中间件:
DOWNLOADER_MIDDLEWARES = {
   'JobSpider.middlewares.JSPageMiddleware': 1,
}

三、缺点

我们将scrapy的异步下载改成了浏览器同步模式,大大降低了性能,为了实现selenium也异步,需要重写scrapy里的downloader,必须要熟悉twist异步框架,GitHub上就有许多插件,比如scrapy-phantomjs-downloader

相关文章

  • Scrapy爬虫——Selenium集成到scrapy

    有条件的请支持慕课实战正版课程,本blog仅仅是归纳总结,自用。 理论上,控制流量,selenium完全模拟人类操...

  • selenium 不加载图片设置 selenium集成到Scra

    selenium不加载图片 selenium集成到Scrapy 1. 自定义一个middlewares 2. 在s...

  • python爬虫常识

    一、简述aiohttp、Scrapy、ScrapyRedis、Requests、Selenium 五个爬虫框架都各...

  • Pycharm+Scrapy框架运行爬虫糗事百科(无items数

    scrapy爬虫框架 qsbk.py 爬虫代码 import scrapy'''scrapy框架爬虫流程:发送请求...

  • Scrapy笔记

    Scrapy笔记 pip 指定源安装模块 创建Scrapy项目 创建Scrapy爬虫程序 启动Scrapy爬虫 在...

  • 爬虫类

    selenium,splinter,webbrowser浏览器操作 scrapy爬虫 关于爬取斗鱼弹幕http:/...

  • scrapy爬虫

    运行爬虫 scrapy crawl +<爬虫名字>Scrapy的安装:pip install scrapy创建s...

  • 第八章 scrapy进阶

    scrapy 进阶 标签(空格分隔): python scrapy selenium selenium动态网页与请...

  • 深度爬虫

    scrapy深度爬虫 1.深度爬虫概述2.scrapy Spider实现的什么爬虫3.scrapy CrawlSp...

  • scrapy笔记

    1 scrapy的运行原理 参考:Learning Scrapy笔记(三)- Scrapy基础Scrapy爬虫入门...

网友评论

  • 腿长袖子短:from scrapy.xlib.pydispatch import dispatcher
    引入这个scrapy直接停止报错,说以已经弃用了
  • 大诗兄_zl:请问有详细的参考吗,对中间件这里很费解

本文标题:Scrapy爬虫——Selenium集成到scrapy

本文链接:https://www.haomeiwen.com/subject/ipafyxtx.html