用于渲染javascript的scrapy-splash用法

时间:2016-10-26 12:22:26

标签: javascript python python-2.7 scrapy scrapy-spider

这是我的previous quesion

的后续跟进

我安装了splash和scrapy-splash。

并且跟随instructions进行了scrapy-splash。

我按如下方式编辑了我的代码:

import scrapy
from scrapy_splash import SplashRequest

class CityDataSpider(scrapy.Spider):
    name = "citydata"

    def start_requests(self):
        urls = [
            'http://www.city-data.com/advanced/search.php#body?fips=0&csize=a&sc=2&sd=0&states=ALL&near=&nam_crit1=6914&b6914=MIN&e6914=MAX&i6914=1&nam_crit2=6819&b6819=15500&e6819=MAX&i6819=1&ps=20&p=0',
            'http://www.city-data.com/advanced/search.php#body?fips=0&csize=a&sc=2&sd=0&states=ALL&near=&nam_crit1=6914&b6914=MIN&e6914=MAX&i6914=1&nam_crit2=6819&b6819=15500&e6819=MAX&i6819=1&ps=20&p=1',
            ]
        for url in urls:
            yield SplashRequest(url=url, callback=self.parse)

    def parse(self, response):
        page = response.url.split("/")[-2]
        filename = 'citydata-%s.html' % page
        with open(filename, 'wb') as f:
            f.write(response.body)
        self.log('Saved file %s' % filename)

但我仍然得到相同的输出。只生成一个html文件,结果仅适用于http://www.city-data.com/advanced/search.php

代码中是否有任何错误或请提出任何其他建议。

1 个答案:

答案 0 :(得分:1)

首先,我想从你的上一个问题“@paul trmbrth”写道中找出一些可能的混淆点:

  

URL片段(即#body之后和之后的所有内容)不会发送到服务器,只会获取http://www.city-data.com/advanced/search.php

     

因此,对于Scrapy,对[...]和[...]的请求是相同的资源,所以它只获取一次。它们的URL片段不同。

URI标准规定数字符号(#)用于表示片段的开头,这是URL的最后一部分。在大多数/所有浏览器中,除“#”之外的任何内容都不会传输。 然而 ,AJAX网站使用Javascript的window.location.hash抓取URL片段并使用它来执行其他AJAX调用是相当常见的。我提出这个问题是因为city-data.com就是这样做的,这可能会让你感到困惑,因为它实际上会为浏览器中的每个网址带回两个不同的网站。

默认情况下,Scrapy会删除网址片段,因此它会将两个网址报告为“http://www.city-data.com/advanced/search.php”,并过滤第二个网址。

完成所有这些操作后,从page = response.url.split("/")[-2]filename = 'citydata-%s.html' % page的组合中删除网址中的“#body”后仍会出现问题。您的网址都没有重定向,因此提供的网址将填充response.url字符串。

隔离它,我们得到以下结果:

>>> urls = [
>>>     'http://www.city-data.com/advanced/search.php?fips=0&csize=a&sc=2&sd=0&states=ALL&near=&nam_crit1=6914&b6914=MIN&e6914=MAX&i6914=1&nam_crit2=6819&b6819=15500&e6819=MAX&i6819=1&ps=20&p=0',
>>>     'http://www.city-data.com/advanced/search.php?fips=0&csize=a&sc=2&sd=0&states=ALL&near=&nam_crit1=6914&b6914=MIN&e6914=MAX&i6914=1&nam_crit2=6819&b6819=15500&e6819=MAX&i6819=1&ps=20&p=1',
>>> ]
>>> for url in urls:
...     print(url.split("/")[-2])

advanced
advanced

因此,对于这两个网址,您正在提取相同的信息,这意味着当您使用filename = 'citydata-%s.html' % page时,您将获得相同的文件名,我认为这将是'citydata-advanced.html ”。第二次调用时,你将覆盖第一个文件。

根据您对数据的处理方式,您可以将其更改为附加到文件,或将文件名变量修改为唯一的内容,例如:

from urlparse import urlparse, parse_qs

import scrapy
from scrapy_splash import SplashRequest

class CityDataSpider(scrapy.Spider):

    [...]

    def parse(self, response):
        page = parse_qs(urlparse(response.url).query).get('p')
        filename = 'citydata-%s.html' % page
        with open(filename, 'wb') as f:
            f.write(response.body)
        self.log('Saved file %s' % filename)