使用Scrapy递归地爬取一个网站

8
我正在尝试使用Scrapy爬取一个网站。
以下是我根据http://thuongnh.com/building-a-web-crawler-with-scrapy/编写的代码。(原始代码完全无法工作,所以我试图重建它。)
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders             import Spider
from scrapy.selector         import HtmlXPathSelector
from nettuts.items            import NettutsItem
from scrapy.http            import Request
from scrapy.linkextractors import LinkExtractor


class MySpider(Spider):
    name = "nettuts"
    allowed_domains = ["net.tutsplus.com"]
    start_urls = ["http://code.tutsplus.com/posts?"]
    rules = [Rule(LinkExtractor(allow = ('')), callback = 'parse', follow = True)]

    def parse(self, response):
        hxs  = HtmlXPathSelector(response)
        item = []

        titles    = hxs.xpath('//li[@class="posts__post"]/a/text()').extract()
        for title in titles:
            item             = NettutsItem()
            item["title"]     = title
            yield item
        return

问题在于爬虫可以访问起始页面,但之后无法抓取任何页面。

这个类的例子用法是什么? - Caridorc
1
@Caridorc,我们正在谈论Scrapy。它有一个带有不同命令的scrapy cli,并且知道如何在项目中选择Scrapy爬虫并启动它们。谢谢。 - alecxe
2个回答

14

以下是一个不错的开始:

"使用Scrapy递归地爬取网站"有两种用例。

A) 我们只想通过表格的分页按钮在整个网站中移动并获取数据。这相对简单。

class TrainSpider(scrapy.Spider):
    name = "trip"
    start_urls = ['somewebsite']
    def parse(self, response):
        ''' do something with this parser '''
        next_page = response.xpath("//a[@class='next_page']/@href").extract_first()
        if next_page is not None:
            next_page = response.urljoin(next_page)
            yield scrapy.Request(next_page, callback=self.parse)`

观察最后四行。这里:

  1. 我们从“下一页”分页按钮的下一页xpath中获取下一页链接。
  2. if条件检查是否到达分页结束。
  3. 使用urljoin将此链接(在步骤1中获得)与主网址连接起来。
  4. 对“parse”回调方法进行递归调用。

B)我们不仅要跨越页面,还要从该页面中的一个或多个链接中提取数据。

class StationDetailSpider(CrawlSpider):
    name = 'train'
    start_urls = [someOtherWebsite]
    rules = (
        Rule(LinkExtractor(restrict_xpaths="//a[@class='next_page']"), follow=True),
        Rule(LinkExtractor(allow=r"/trains/\d+$"), callback='parse_trains')
    )
    def parse_trains(self, response):
        '''do your parsing here'''

在此,注意:

  1. 我们正在使用'scrapy.Spider'父类的'CrawlSpider'子类

  2. 我们已设置为“Rules”

    a)第一条规则只检查是否有“next_page”可用并跟随它。

    b)第二条规则请求页面上格式为“/trains/12343”的所有链接,然后调用“parse_trains”执行解析操作。

  3. 重要提示:请注意,我们不想在这里使用常规的“parse”方法,因为我们正在使用“CrawlSpider”子类。该类也具有“parse”方法,因此我们不想覆盖它。只需记住将回调方法命名为除“parse”之外的其他名称即可。


7
问题在于你使用的是哪个Spider类作为基础。 scrapy.Spider是一个简单的爬虫,不支持规则和链接提取器。 相反,使用CrawlSpider
class MySpider(CrawlSpider):

非常感谢您的回答,它非常有帮助。 我仍然有问题。我认为“rules”这一行是不正确的。我正在尝试插入不同的值,但它没有起作用。 我可以再问一个提示吗? - Macro
第一个要爬取的页面是:http://code.tutsplus.com/posts?page=1,下一页是:http://code.tutsplus.com/posts?page=2,以此类推。 - Macro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接