简析selenium和scrapy对接

selenium和 Scrapy对接

爬取某些需要动态加载的页面,使用selenium模块是诸多方法中的一个,直接使用selenium模块并不复杂,
在Scrapy框架下依然可以使用该模块解决动态加载的问题.

首先再熟悉下流程

Scrapy的基本流程图如下

  • 引擎负责控制系统所有组件之间的数据流,并在某些动作发生时触发事件。

  • 调度器(用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回.

  • 用于下载网页内容, 并将网页内容返回给EGINE

  • SPIDERS用来解析responses,并且提取items,或者发送新的请求

  • 管道在items被提取后负责处理它们,主要包括清理、验证、持久化(比如存到数据库)等操作

  • 下载器中间件位于Scrapy引擎和下载器之间,主要用来处理从EGINE传到DOWLOADER的请求request,已经从DOWNLOADER传到EGINE的响应response,

  • 爬虫中间件位于EGINE和SPIDERS之间,主要工作是处理SPIDERS的输入(即responses)和输出(即requests)

基本思路

直接解析接受动态加载页面的响应,无法获得预期的数据,所以我们可以在下载中间件中拦截该响应,并篡改响应,从而获取我们想要的数据.

1. 准备工作

在 setting.py 下:

 DOWNLOADER_MIDDLEWARES = {
    'news163.middlewares.News163DownloaderMiddleware': 543,
}

在 name_spider.py 下:
实例化浏览器对象:
以谷歌浏览器为例,

driver = webdriver.Chrome(executable_path='...')

或:
实例化浏览器对象(无头浏览器)

chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
driver = webdriver.Chrome(options=chrome_options,executable_path='...')

ps:不要在下载中间件中实例化,会浪费资源降低效率.

在爬虫类下,准备一个列表,用来存放需要动态加载的页面的 url:

start_urls = ['url1','url2','url3'......]

2. 拦截响应,并篡改

下载中间件类:

  1. 判断该响应对应的url是否在,准备好的列表中,若不在则无需篡改,否则进行下一步
  2. 调用无头浏览器,书写逻辑获取响应内容
  3. 构造响应返回给引擎,

代码

import time
from scrapy.http import HtmlResponse

......

def process_response(self, request, response, spider):
    driver = spider.driver
    if request.url in spider.start_urls:
        driver.get(request.url)
        time.sleep(3)
        js = 'window.scrollTo(0, document.body.scrollHeight)'
        driver.execute_script(js)  # 向下滑
        time.sleep(3)
        response_selenium = driver.page_source  # 响应内容
        return HtmlResponse(url=driver.current_url, body=response_selenium, encoding='utf-8', request=request)
    # 构造响应,
    return response

这样我们就能篡改响应,爬取到需要动态加载页面的数据了

你可能感兴趣的:(简析selenium和scrapy对接)