【问题标题】:How do i create rules for a crawlspider using scrapy如何使用scrapy为爬虫创建规则
【发布时间】:2026-02-02 22:40:01
【问题描述】:
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 教程,但它几乎让我无法理解。我在这里问我要做什么来创建我的规则,以及如何。我似乎也无法让我的条件正常工作,代码要么只返回第一个项目并且不管条件如何都停止,或者抓住一切,再次不管条件。我知道它的代码可能很混乱,但我仍在努力学习。随意修改代码或提供其他建议

【问题讨论】:

    标签: python web-crawler scrapy


    【解决方案1】:

    严格来说,这并不能回答问题,因为我的代码使用 BaseSpider 而不是 CrawlSpider,但它确实满足了 OP 的要求,所以......

    注意事项:

    1. 由于所有的分页链接都不可用(前九个,然后是后两个),我采用了一种有点hacktastic 的方法。使用parse 回调中的第一个响应,我搜索具有“下一个”类的链接(只有一个,所以看看它对应于哪个链接),然后找到它的前一个兄弟。这让我可以掌握 seinen 类别的总页数(目前为 45)。
    2. 接下来,我们为要由parse_item 回调处理的第一页生成一个Request 对象。
    3. 然后,鉴于我们已经确定总共有 45 个页面,我们为“./seinen/2.htm”生成一系列请求对象,一直到“./seinen/45.htm”。
    4. 由于rating 是一个列表并且它的值是浮点数(基于条件是4.5,我应该已经意识到),修复遇到的错误的方法是循环遍历评级列表并强制每个item 是一个浮点数。

    不管怎样,看看下面的代码,看看它是否有意义。从理论上讲,您应该能够轻松地扩展此代码以抓取多个类别,尽管这留给 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
    

    【讨论】:

    • 啊,有道理,我尝试了 float(rating) 但由于某种原因不起作用,谢谢。我将重新测试代码并返回结果
    • 它说我不能把 rating 变成一个 int 因为它是一个列表,我如何让它不返回一个列表?