Scrapy-splash用于渲染javascript



这是我上一个问题的后续问题

我安装了splash和scrapy-splash。

并且也遵循了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

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

首先,我想澄清你上一个问题中可能存在的混淆点,"@paul trmbrth"写道:

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

所以对于Scrapy,请求[…]和……]是相同的资源,所以只需要fetch一次。它们的区别只在于URL片段。

URI标准规定使用数字符号(#)来表示片段的开始,这是URL的最后一部分。在大多数/所有浏览器中,除了"#"之外什么都不会传输。然而, AJAX站点利用Javascript的window.location.hash抓取URL片段并使用它来执行额外的AJAX调用是相当常见的。我提到这个是因为citydata.com就是这样做的,这可能会让你感到困惑,因为它实际上会在浏览器中为每个url返回两个不同的站点。

Scrapy在默认情况下会删除URL片段,所以它会将两个URL都报告为"http://www.city-data.com/advanced/search.php",并过滤第二个。


有了所有这些,仍然会有问题,当你从url中删除"#body"由page = response.url.split("/")[-2]filename = 'citydata-%s.html' % page的组合造成的。这两个URL都不是重定向的,所以所提供的URL将填充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

所以,对于两个URL,你提取相同的信息,这意味着当你使用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)

最新更新