【问题标题】:Scrapy only returns limited amount of outputScrapy 只返回有限的输出量
【发布时间】:2014-05-06 10:19:30
【问题描述】:

我有一个爬取多个 start_url 的 Spider,但问题是我只收到有限数量的输出。但是,当我抓取一个 start_url 时,它确实会在页面无限滚动之前返回所有结果。这是我的蜘蛛代码:

from scrapy.spider import Spider
from scrapy.selector import Selector
from Pinterest.items import PinterestItem

class PinterestSpider(Spider):
    name = "pinterest"
    allowed_domains = ["pinterest.com"]
    start_urls = [
        "http://www.pinterest.com/jetsetterphoto/pins/",
        "http://www.pinterest.com/llbean/pins/",        
        "http://www.pinterest.com/nordstrom/pins/"
    ]

    def parse(self, response):
        hxs = Selector(response)
        pin_links = hxs.xpath("//div[@class='pinHolder']/a/@href").extract()
        repin_counts = hxs.xpath("//em[@class='socialMetaCount repinCountSmall']/text()").extract()
        like_counts = hxs.xpath("//em[@class='socialMetaCount likeCountSmall']/text()").extract()
        comment_counts = hxs.xpath("//em[@class='socialMetaCount commentCountSmall']/text()").extract()
        board_names = hxs.xpath("//div[@class='creditTitle']/text()").extract()
        pin_descriptions = hxs.xpath("//p[@class='pinDescription']/text()").extract()

        items = []
        for pin_link, repin_count, like_count, comment_count, board_name, pin_description in zip(pin_links, repin_counts, like_counts, comment_counts, board_names, pin_descriptions):
            item = PinterestItem()
            item["pin_link"] = pin_link.strip()
            item["repin_count"] = repin_count.strip()
            item["like_count"] = like_count.strip()
            item["comment_count"] = comment_count.strip()
            item["board_name"] = board_name.strip()
            item["pin_description"] = pin_description.strip()
            items.append(item)
        return items

我可以看到爬虫确实爬取了 start_urls,但在 JSON 文件中只返回了 16 行输出。当我使用一个 start_url 时,它会提供更多的输出行(所有这些行,直到页面的无限滚动)。我可以在设置中执行的请求数量是否有限制?我尝试寻找类似的问题,但找不到任何与我相似的问题。有什么想法吗?

编辑:它可以与每个域的并发请求设置有关吗? http://doc.scrapy.org/en/latest/topics/settings.html 他们在这里指定最大值为 8,我每个域正好有 8 行输出。默认情况下,并发请求的总数为 16,这可以解释为什么我只得到 2 个 start_urls 的结果。如果我更改默认设置,我将测试这是否有效(我不知道这对其他人是否有意义)。

编辑:我想将此添加到我的蜘蛛以提取基本信息:

for BasicInfo in selector.css('div.userProfilePage'):
    item["company_pins"] = get(pin.css('div.PinCount::text'))
    item["company_likes"] = get(pin.css('ul.userStats li~ li+ li a::text'))
    item["company_name"] = get(pin.css('h1.userProfileHeaderName::text'))
    item["company_followers"] = get(pin.css('a.FollowerCount .buttonText::text'))

那么代码会是这样的:

def parse(self, response):
    selector = Selector(response)
    items = []
    for pin in selector.css('div.pinWrapper'):
        item = PinterestItem()            
        item["pin_link"] = get(pin.css('div.pinHolder a::attr(href)'))
        item["repin_count"] = get(pin.css('em.repinCountSmall::text'))
        item["like_count"] = get(pin.css('em.likeCountSmall::text'))
        item["comment_count"] = get(pin.css('em.commentCountSmall::text'))
        item["board_name"] = get(pin.css('div.creditTitle::text'))
        item["pin_description"] = get(pin.css('p.pinDescription::text'))

        items.append(item)
    self.log("extracted %d item(s) from %s" % (len(items), response.url))
    return items

def parse(self, response):
    selector = Selector(response)
    items = []
    for BasicInfo in selector.css('div.userProfilePage'):
        item["company_pins"] = get(pin.css('div.PinCount::text'))
        item["company_likes"] = get(pin.css('ul.userStats li~ li+ li a::text'))
        item["company_name"] = get(pin.css('h1.userProfileHeaderName::text'))
        item["company_followers"] = get(pin.css('a.FollowerCount .buttonText::text'))

items.append(item)
    self.log("extracted %d item(s) from %s" % (len(items), response.url))
    return items

我知道这是错误的,但我不知道在哪里或如何放置它。我应该使用请求包含回调吗?

【问题讨论】:

  • 可能是用CrawlSpider 覆盖parse 方法的常见问题:你应该避免这种情况,除非你用规则和东西重新创建CrawlSpider 的逻辑。在此处查看警告:doc.scrapy.org/en/latest/topics/spiders.html#crawling-rules
  • 感谢您的回复。当我使用普通的 Spider 时,我遇到了同样的问题,它给了我完全相同的输出。
  • 我编辑了帖子,也许是默认并发请求有问题?
  • 显然不是。

标签: json output scrapy


【解决方案1】:

我已经重写了你的蜘蛛:

  • 循环 <div class="pinWrapper"> 元素,
  • 并相对于每个pin 使用CSS 选择器(您当然可以使用相对的XPath 表达式,即以“.//”而不是“//”开头://div[@class='creditTitle']/text() 应该是.//div[@class='creditTitle']/text()

请注意,::text::attr(attribute_name) 是 Scrapy 添加到 CSS 选择器语法的扩展

以下代码每页抓取 25 个项目:

import operator
from scrapy.spider import Spider
from scrapy.selector import Selector, SelectorList
#from Pinterest.items import PinterestItem
from scrapy.item import Item, Field

class PinterestItem(Item):
    pin_link = Field()
    repin_count = Field()
    like_count = Field()
    comment_count = Field()
    board_name = Field()
    pin_description = Field()

def get(selectorlist):
    for i in selectorlist.extract():
        return i.strip()

class PinterestSpider(Spider):
    name = "pinterest"
    allowed_domains = ["pinterest.com"]
    start_urls = [
        "http://www.pinterest.com/jetsetterphoto/pins/",
        "http://www.pinterest.com/llbean/pins/",
        "http://www.pinterest.com/nordstrom/pins/"
    ]

    def parse(self, response):
        selector = Selector(response)
        items = []
        for pin in selector.css('div.pinWrapper'):
            item = PinterestItem()
            item["pin_link"] = get(pin.css('div.pinHolder a::attr(href)'))
            item["repin_count"] = get(pin.css('em.repinCountSmall::text'))
            item["like_count"] = get(pin.css('em.likeCountSmall::text'))
            item["comment_count"] = get(pin.css('em.commentCountSmall::text'))
            item["board_name"] = get(pin.css('div.creditTitle::text'))
            item["pin_description"] = get(pin.css('p.pinDescription::text'))
            items.append(item)
        self.log("extracted %d item(s) from %s" % (len(items), response.url))
        return items

【讨论】:

  • 哇,这成功了。我自己永远也想不通。循环元素(即pinWrapper)而不是不这样做主要是一个更好的选择吗?非常感谢!!
  • 我发现这种方式更容易编写和维护,当某些 XPath 结果中缺少某些数据元素时,我想知道zip() 的行为如何
  • 每个“pin”的最高级别 CSS 选择器是 div.Grid > div.GridItems > div.item。如果您需要的数据在文档树中较高,您可以使用“pin loop”之外的其他选择器提取它,然后使用它们向您的项目添加一些信息(所有项目的信息相同)。我想这一切都取决于你的用例。
  • 感谢您的回答。我删除了我的评论,因为我没有提供足够的信息。与此同时,我正在研究如何使用它。我编辑了我的初始问题,这是要走的路还是?附言。我刚刚编写的BasicInfo来说明我要抓取的内容
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-03
  • 1970-01-01
  • 2014-12-29
  • 1970-01-01
  • 2023-03-08
相关资源
最近更新 更多