Selenium集成到Scrapy中

1. 新建知乎爬虫:
> scrapy genspider zhihu www.zhihu.com

编写zhihu spider的页面解析函数parse(),由于此函数被要求返回一个可迭代对象,所以这里直接返回一个空列表作为测试。

# -*- coding: utf-8 -*-
# @Author  : One Fine
# @File    : zhihu.py
import scrapy

class ZhihuSpider(scrapy.Spider):
    name = 'zhihu'
    allowed_domains = ['www.zhihu.com']
    start_urls = ['http://www.zhihu.com/']

    def parse(self, response):
        yield []  # 测试

注:这里重点介绍将Selenium集成到Scrapy中,关于zhihu spider的具体逻辑将忽略。

2.编写Downloader Middleware

先实现Downloader Middleware的process_request()方法,当返回为Response对象(htmlResponse是其子类)时,Scrapy将不会调用任何其他的process_request方法,将直接返回这个response对象。

from selenium import webdriver
from time import sleep
from scrapy.http import HtmlResponse

class JSPageMiddleware(object):
    # 通过Chrome请求动态网页
	def __init__(self):
        self.browser = webdriver.Chrome(executable_path='D:/selenium/chromedriver.exe')
        super(JSPageMiddleware, self).__init__()

    def process_request(self, request, spider):
        # htmlResponse避免scrapy到downloader中重复下载。
        # 一旦遇到htmlResponse,scrapy将不会在再向downloader发送请求,而是直接返回给spider。
        # 注意,这里是同步请求
        if spider.name == 'zhihu':
            self.browser.get(request.url)
            sleep(3)
            print("访问{0}".format(request.url))
            return HtmlResponse(url=self.browser.current_url, body=self.browser.page_source,
                                encoding='utf8', request=request)
3.激活Downloader中间件(Downloader Middlewares)

要启用Downloader中间件(Downloader Middlewares),可以将其加入到settings.py中的DOWNLOADER_MIDDLEWARES设置中。 该设置是一个字典,键为中间件的路径,值为中间件的顺序(order)。

DOWNLOADER_MIDDLEWARES = {
    'spider_pjt1.middlewares.JSPageMiddleware': 1,
}
4. 测试
# -*- coding: utf-8 -*-
# @Author  : One Fine
# @File    : main.py

from scrapy.cmdline import execute

import sys
import os

sys.path.append(os.path.dirname(os.path.abspath(__file__)))

# 调用execute()函数来执行命令,此方法传递一个数组作为参数
execute(["scrapy", "crawl", "zhihu"])

然而,我们发现通过Selenium启动的浏览器并没有关闭,我们来改写一下zhihu.py文件。

5. 改写zhihu.py文件和Downloader Middleware

这里涉及Scrapy信号量的知识,暂时不做解释。

# -*- coding: utf-8 -*-
# @Author  : One Fine
# @File    : zhihu.py

import scrapy
from selenium import webdriver
from scrapy.xlib.pydispatch import dispatcher
from scrapy import signals

class ZhihuSpider(scrapy.Spider):
    name = 'zhihu'
    allowed_domains = ['www.zhihu.com']
    start_urls = ['http://www.zhihu.com/']

    def __init__(self):
        self.browser = webdriver.Chrome(executable_path='D:/selenium/chromedriver.exe')
        super(ZhihuSpider, self).__init__()
        # zhihu爬虫退出的时候关闭浏览器
        dispatcher.connect(self.spider_closed, signals.spider_closed)

    def spider_closed(self):
        # 信号量的回调函数
        print("spider closed")
        self.browser.quit()

    def parse(self, response):
        yield []

相应的,Downloader Middleware有需要相应的修改:

from time import sleep
from scrapy.http import HtmlResponse

class JSPageMiddleware(object):

    def process_request(self, request, spider):
        if spider.name == 'zhihu':
            spider.browser.get(request.url)
            sleep(3)
            return HtmlResponse(url=spider.browser.current_url, body=spider.browser.page_source,
                                encoding='utf8', request=request)

至此, 我们已经将Selenium集成到Scrapy中。


参考:
爬虫(十五):scrapy中的settings详解 http://www.cnblogs.com/felixwang2/p/8798653.html
八.Scrapy 学习下Spider中间件Spider Middlewares https://blog.csdn.net/beyond_f/article/details/74626311
改写scrapy中的middlewares组件,建立user-agent池和IP代理池达到反爬的效果 https://blog.csdn.net/qq_41020281/article/details/79436643

posted @ 2019-03-07 18:24  onefine  阅读(326)  评论(0编辑  收藏  举报