只用scrapy获取一行输出到json文件

Posted

技术标签:

【中文标题】只用scrapy获取一行输出到json文件【英文标题】:Only getting one line of output with scrapy to json file 【发布时间】:2014-06-19 23:57:14 【问题描述】:

好的,所以我是一般编程的新手,并且专门为此目的使用 Scrapy。我编写了一个爬虫来从 pinterest.com 上的 pin 获取数据。问题是我以前从我正在抓取的页面上的所有 pin 获取数据,但现在我只获取第一个 pin 的数据。

我认为问题在于管道或蜘蛛本身。在我将“条带”添加到蜘蛛以摆脱空白之后,有些东西发生了变化,但是当我将它改回来时,我得到了相同的输出,但随后出现了空白。这是蜘蛛:

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/llbean/pins/"]

    def parse(self, response):
        hxs = Selector(response)
        item = PinterestItem()
        items = []
        item ["pin_link"] = hxs.xpath("//div[@class='pinHolder']/a/@href").extract()[0].strip()
        item ["repin_count"] = hxs.xpath("//em[@class='socialMetaCount repinCountSmall']/text()").extract()[0].strip()
        item ["like_count"] = hxs.xpath("//em[@class='socialMetaCount likeCountSmall']/text()").extract()[0].strip()
        item ["board_name"] = hxs.xpath("//div[@class='creditTitle']/text()").extract()[0].strip()
        items.append(item)
        return items

这是我的管道:

from scrapy.xlib.pydispatch import dispatcher
from scrapy import signals
from scrapy.contrib.exporter import JsonLinesItemExporter

class JsonLinesExportPipeline(object):

    def __init__(self):
        dispatcher.connect(self.spider_opened, signals.spider_opened)
        dispatcher.connect(self.spider_closed, signals.spider_closed)
        self.files = 

    def spider_opened(self, spider):
        file = open('%s_items.json' % spider.name, 'w+b')
        self.files[spider] = file
        self.exporter = JsonLinesItemExporter(file)
        self.exporter.start_exporting()

    def spider_closed(self, spider):
        self.exporter.finish_exporting()
        file = self.files.pop(spider)
        file.close()

    def process_item(self, item, spider):
        self.exporter.export_item(item)
        return item

当我使用命令“scrapy crawl pinterest”时,这是我在 JSON 文件中得到的输出:

"pin_link": "/pin/94716398388365841/", "board_name": "Outdoor Fun", "like_count": "14", "repin_count": "94"

这正是我想要的输出,但我只从一个 pin 获得它,而不是从页面上的所有 pin 获得。我花了很多时间阅读类似的问题,但我找不到任何类似的问题。关于什么是错的任何想法?提前致谢!

编辑:哦,我猜是因为剥离函数之前的 [0]?抱歉,我刚刚意识到这可能是问题所在......

编辑:嗯,这不是问题。我很确定它必须与 strip 功能有关,但我似乎无法正确使用它来获取多个引脚作为输出。解决方案可以成为这个问题的一部分吗?:Scrapy: Why extracted strings are in this format? 我看到一些重叠,但我不知道如何使用它。

编辑:好的,所以当我这样修改蜘蛛时:

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/llbean/pins/"]

def parse(self, response):
    hxs = Selector(response)
    sites = hxs.xpath("//div[@class='pinWrapper']")
    items = []
    for site in sites:
        item = PinterestItem()        
        item ["pin_link"] = site.select("//div[@class='pinHolder']/a/@href").extract()[0].strip()
        item ["repin_count"] = site.select("//em[@class='socialMetaCount repinCountSmall']/text()").extract()[0].strip()
        item ["like_count"] = site.select("//em[@class='socialMetaCount likeCountSmall']/text()").extract()[0].strip()
        item ["board_name"] = site.select("//div[@class='creditTitle']/text()").extract()[0].strip()
        items.append(item)
    return items

它确实给了我几行输出,但显然都具有相同的信息,因此它爬取了页面上引脚数的项目,但都具有相同的输出:

"pin_link": "/pin/94716398388371133/", "board_name": "Take Me Fishing", "like_count": "3", "repin_count": "21"
"pin_link": "/pin/94716398388371133/", "board_name": "Take Me Fishing", "like_count": "3", "repin_count": "21"
"pin_link": "/pin/94716398388371133/", "board_name": "Take Me Fishing", "like_count": "3", "repin_count": "21"
"pin_link": "/pin/94716398388371133/", "board_name": "Take Me Fishing", "like_count": "3", "repin_count": "21"

等等

【问题讨论】:

尝试让步,而不是返回;如果对您有帮助,请参阅github.com/ocwc/gatherer/blob/master/gatherer/spiders/… 感谢您的回复。正如我所说,我是scrapy的新手,所以我不完全明白我应该做什么才能屈服。如果我产生项目,我会得到一个空白的 JSON 文件。我应该包括您使用的请求功能吗?如果是,我应该如何使用它?谢谢 好的,我尝试使用yield,但现在它返回的输出与我使用return时相同。有什么想法吗? extract()[0] 总是取结果中的第一项,这就是为什么所有结果都相同 【参考方案1】:

我没有用过 Scrapy,所以这是一个疯狂的猜测。

您的选择器正在拉回多个结果。然后,您从每个列表中选择第一个值(使用切片 [0]),创建一个名为 itemsingle item,在返回之前将其附加到 items 列表中那。似乎没有循环选择器返回的所有可能结果。

因此,提取所有结果,然后遍历它们以创建您的 items 列表:

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()
    board_names = hxs.xpath("//div[@class='creditTitle']/text()").extract()

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

【讨论】:

感谢您的回复。当我尝试此操作时,出现以下错误:“UnboundLocalError:分配前引用的局部变量'repin_count'”。这是因为在项目分配之前提到了它(item [“repin_count”] = repin_count?我不确定这个错误是什么意思。 @Marky 我的错,我在 zip() 中使用了单数名称,而不是在 repin_countslike_counts 中使用复数。我已经更新了上面的例子。 啊啊太棒了!现在可以了!现在唯一的事情是我仍然有空格和 \n 作为输出。我现在可以添加“条带”或规范化空间,还是我会回到同样的问题?我会接受的。 @Marky 是的,你可以,我也打算包括在内。再次更新:) 非常感谢,我在这个问题上卡了很长时间!

以上是关于只用scrapy获取一行输出到json文件的主要内容,如果未能解决你的问题,请参考以下文章

Scrapy - 输出到多个 JSON 文件

Scrapy 解析 JSON 输出

如何在scrapy框架下用python爬取json文件

Scrapy 从站点下载 json 文件?

将 Scrapy Python 输出写入 JSON 文件

从python脚本调用scrapy而不创建JSON输出文件