scrapy-spash:SplashRequest响应对象在scrapy爬网与CrawlerProcess调用之间有所不同

时间:2019-03-10 03:41:20

标签: python web-scraping scrapy web-crawler scrapy-splash

我想使用scrapy-splash来获取目标页面的html和screenshot png。我需要能够以编程方式调用它。根据{{​​3}},指定

endpoint='render.json'

传递参数

'png': 1

应导致一个响应对象('scrapy_splash.response.SplashJsonResponse')具有.data属性,该属性包含表示目标页面png屏幕截图的JSON解码数据。

使用调用蜘蛛程序(此处称为“搜索”)时

scrapy crawl search

结果与预期的一样,其中response.data ['png']包含png数据。

但是,如果通过scrapy的CrawlerProcess调用它,则会返回另一个响应对象:“ scrapy.http.response.html.HtmlResponse”。该对象没有.data属性。

代码如下:

import scrapy
from scrapy.crawler import CrawlerProcess
from scrapy_splash import SplashRequest
import base64

RUN_CRAWLERPROCESS = False

if RUN_CRAWLERPROCESS:
    from crochet import setup
    setup()

class SpiderSearch(scrapy.Spider):
    name = 'search'
    user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'

    def start_requests(self):
        urls = ['https://www.google.com/search?q=test', ]
        splash_args = {
            'html': 1,
            'png': 1,
            'width': 1920,
            'wait': 0.5,
            'render_all': 1,
        }
        for url in urls:
            yield SplashRequest(url=url, callback=self.parse, endpoint='render.json', args=splash_args, )

    def parse(self, response):
        print(type(response))
        for result in response.xpath('//div[@class="r"]'): 
            url = str(result.xpath('./a/@href').extract_first())
            yield {
                'url': url
            }

        png_bytes = base64.b64decode(response.data['png'])
        with open('google_results.png', 'wb') as f:
            f.write(png_bytes)

        splash_args = {
            'html': 1,
            'png': 1,
            'width': 1920,
            'wait': 2,
            'render_all': 1,
            'html5_media': 1,
        }
        # cue the subsequent url to be fetched (self.parse_result omitted here for brevity)
        yield SplashRequest(url=url, callback=self.parse_result, endpoint='render.json', args=splash_args)

if RUN_CRAWLERPROCESS:
    runner = CrawlerProcess({'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'})
    #d = runner.crawl(SpiderSearch)
    #d.addBoth(lambda _: reactor.stop())
    #reactor.run()
    runner.crawl(SpiderSearch)
    runner.start()

重新定级:

RUN_CRAWLERPROCESS = False 

并通过

调用
scrapy crawl search

响应类型

class 'scrapy_splash.response.SplashJsonResponse'

但要设置

RUN_CRAWLERPROCESS = True 

并使用CrawlerProcess运行脚本会导致响应类型

class 'scrapy.http.response.html.HtmlResponse'

(ps,我在ReactorNotRestartable上遇到了一些麻烦,因此按照spashy doc中的描述使用了钩针编织,这似乎已经解决了问题。我承认我不明白为什么,但是假设它不相关...)

关于如何调试此程序的任何想法?

1 个答案:

答案 0 :(得分:0)

如果您以独立脚本的形式运行此代码,则设置模块将永远不会加载,并且您的搜寻器将不会知道Splashy中间件(这就是您在{{ 1}})。

您可以通过调用.data并将结果传递给您的Crawler来在脚本中加载这些设置:

.parse