Scrapy - 解析给定域的所有子页面

时间:2013-03-14 02:38:36

标签: web-scraping scrapy web-crawler

我想使用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

1 个答案:

答案 0 :(得分:4)

由于您是CrawlSpider的子类,不会覆盖parse CrawlSpider的链接抓取逻辑包含在您真正需要的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。最好将蜘蛛的输出保持为生成器,它允许您生成多个项目/请求,而无需创建一个列表来保存它们。