【问题标题】:Scrapy - parsing all sub-pages of a given domainScrapy - 解析给定域的所有子页面
【发布时间】:2013-03-14 02:38:36
【问题描述】:

我想使用 scrapy 解析 kickstarter.com 项目,但不知道如何制作我未在 start_urls 下明确指定的蜘蛛搜索项目。我已经弄清楚了scrapy代码的第一部分(我可以从一个网站提取必要的信息),但我无法让它为域kickstarter.com/projects下的所有项目执行此操作。

根据我的阅读,我相信解析是可能的 (1) 使用起始页面 (kickstarter.com/projects) 上的链接,(2) 使用来自一个项目页面的链接跳转到另一个项目,以及 ( 3) 使用站点地图(我认为 kickstarter.com 没有)来定位要解析的网页。

我已经花了几个小时尝试这些方法中的每一个,但我一无所获。

我使用了scrapy教程代码并在其上构建。

这是目前有效的部分:

from scrapy import log
from scrapy.contrib.spiders import CrawlSpider   
from scrapy.selector import HtmlXPathSelector  

from tutorial.items import kickstarteritem

class kickstarter(CrawlSpider):
    name = 'kickstarter'
    allowed_domains = ['kickstarter.com']    
    start_urls = ["http://www.kickstarter.com/projects/brucegoldwell/dragon-keepers-book-iv-fantasy-mystery-magic"]

    def parse(self, response):
        x = HtmlXPathSelector(response)

        item = kickstarteritem()
        item['url'] = response.url
        item['name'] = x.select("//div[@class='NS-project_-running_board']/h2[@id='title']/a/text()").extract()
        item['launched'] = x.select("//li[@class='posted']/text()").extract()
        item['ended'] = x.select("//li[@class='ends']/text()").extract()
        item['backers'] = x.select("//span[@class='count']/data[@data-format='number']/@data-value").extract()
        item['pledge'] = x.select("//div[@class='num']/@data-pledged").extract()
        item['goal'] = x.select("//div[@class='num']/@data-goal").extract()
        return item

【问题讨论】:

    标签: web-scraping scrapy web-crawler


    【解决方案1】:

    由于您是 CrawlSpider 的子类,不要覆盖 parseCrawlSpider 的链接爬取逻辑包含在 parse 中,这是您真正需要的。

    至于爬行本身,这就是rules 类属性的用途。我还没有测试过,但它应该可以工作:

    from scrapy.contrib.spiders import CrawlSpider
    from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
    from scrapy.contrib.loader import XPathItemLoader
    from scrapy.selector import HtmlXPathSelector
    
    from tutorial.items import kickstarteritem
    
    class kickstarter(CrawlSpider):
        name = 'kickstarter'
        allowed_domains = ['kickstarter.com']    
        start_urls = ['http://www.kickstarter.com/discover/recently-launched']
    
        rules = (
            Rule(
                SgmlLinkExtractor(allow=r'\?page=\d+'),
                follow=True
            ),
            Rule(
                SgmlLinkExtractor(allow=r'/projects/'),
                callback='parse_item'
            )
        )
    
        def parse_item(self, response):
            xpath = HtmlXPathSelector(response)
            loader = XPathItemLoader(item=kickstarteritem(), response=response)
    
            loader.add_value('url', response.url)
            loader.add_xpath('name', '//div[@class="NS-project_-running_board"]/h2[@id="title"]/a/text()')
            loader.add_xpath('launched', '//li[@class="posted"]/text()')
            loader.add_xpath('ended', '//li[@class="ends"]/text()')
            loader.add_xpath('backers', '//span[@class="count"]/data[@data-format="number"]/@data-value')
            loader.add_xpath('pledge', '//div[@class="num"]/@data-pledged')
            loader.add_xpath('goal', '//div[@class="num"]/@data-goal')
    
            yield loader.load_item()
    

    蜘蛛抓取最近启动项目的页面。

    另外,使用yield 代替return。最好将蜘蛛的输出保留为生成器,这样您就可以生成多个项目/请求,而无需创建一个列表来保存它们。

    【讨论】:

    • 我运行了代码,它工作正常。这会刮掉所有最近启动的项目。如果我想抓取所有项目(不仅仅是最近启动的项目),我是否只需更改规则和 start_urls?非常感谢。这是一个巨大的帮助。我不知道我能做些什么来回报你和社区。我会传递善意的。
    • @user2167391:没问题。 Scrapy 真的很棒,但是在网上很难找到例子。至于 Kickstarter,他们很难访问他们的所有项目,所以你必须看看他们都在哪里。
    猜你喜欢
    • 1970-01-01
    • 2014-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 2017-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多