如何使用scrapy为crawlspider创建规则

时间:2013-01-19 18:38:58

标签: python web-crawler scrapy

from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector
from manga.items import MangaItem

class MangaHere(BaseSpider):
    name = "mangah"
    allowed_domains = ["mangahere.com"]
    start_urls = ["http://www.mangahere.com/seinen/"]

    def parse(self,response):
        hxs = HtmlXPathSelector(response)
        sites = hxs.select('//ul/li/div')
        items = []
        for site in sites:
            rating = site.select("p/span/text()").extract()
            if rating > 4.5:
                item = MangaItem()
                item["title"] = site.select("div/a/text()").extract()
                item["desc"] = site.select("p[2]/text()").extract()
                item["link"] = site.select("div/a/@href").extract()
                item["rate"] = site.select("p/span/text()").extract()
                items.append(item)

        return items

我的目标是抓取www.mangahere.com/seinen或该网站上的任何内容。我想浏览每一页并收集大于4.5评级的书籍。我最初是作为一个basespider,并尝试复制和阅读scrapy教程,但它几乎是我的头脑。我在这里问我该怎么做才能创建我的规则,以及如何制定规则。我似乎无法让我的条件工作,代码要么只返回第一个项目并停止,无论条件如何,或抓住所有内容,无论条件如何。我知道它可能是相当混乱的代码,但我仍然在努力学习。随意修改代码或提供其他建议

1 个答案:

答案 0 :(得分:6)

严格地说,由于我的代码使用的是BaseSpider而不是CrawlSpider,因此无法回答这个问题,但它确实满足了OP的要求......

注意事项:

  1. 由于所有的分页链接都不可用(你得到前九个,然后是最后两个),我采用了一种有点黑客的方法。使用parse回调中的第一个响应,我搜索一个带有“next”类的链接(只有一个,所以看看它对应哪个链接),然后找到它的前一个兄弟。这使我能够处理seinen类别中的总页数(目前为45)。
  2. 接下来,我们为parse_item回调处理的第一页生成一个Request对象。
  3. 然后,鉴于我们确定共有45页,我们为“./seinen/2.htm”生成了一系列Request对象,一直到“./seinen/45.htm”。
  4. 由于rating是一个列表,并且它的值是浮点数(我应该在条件为4.5的基础上实现),修复遇到的错误的方法是遍历评级列表和将每个项目都变为浮动。
  5. 无论如何,看看下面的代码,看看它是否有意义。从理论上讲,您应该能够轻松地扩展此代码以抓取多个类别,尽管这只是OP的练习。 :)

    from scrapy.spider import BaseSpider
    from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
    from scrapy.selector import HtmlXPathSelector
    from scrapy.http import Request
    from tutorial.items import MangaItem
    from urlparse import urlparse
    
    class MangaHere(BaseSpider):
        name = "mangah2"
        start_urls = ["http://www.mangahere.com/seinen/"]
        allowed_domains = ["mangahere.com"]
    
        def parse(self, response):
            # get index depth ie the total number of pages for the category
            hxs = HtmlXPathSelector(response)
            next_link = hxs.select('//a[@class="next"]')
            index_depth = int(next_link.select('preceding-sibling::a[1]/text()').extract()[0])
    
            # create a request for the first page
            url = urlparse("http://www.mangahere.com/seinen/")
            yield Request(url.geturl(), callback=self.parse_item)
    
            # create a request for each subsequent page in the form "./seinen/x.htm"
            for x in xrange(2, index_depth):
                pageURL = "http://www.mangahere.com/seinen/%s.htm" % x
                url = urlparse(pageURL)
                yield Request(url.geturl(), callback=self.parse_item)
    
        def parse_item(self,response):
            hxs = HtmlXPathSelector(response)
            sites = hxs.select('//ul/li/div')
            items = []
            for site in sites:
                rating = site.select("p/span/text()").extract()
                for r in rating:
                    if float(r) > 4.5:
                        item = MangaItem()
                        item["title"] = site.select("div/a/text()").extract()
                        item["desc"] = site.select("p[2]/text()").extract()
                        item["link"] = site.select("div/a/@href").extract()
                        item["rate"] = site.select("p/span/text()").extract()
                        items.append(item)
            return items