从多个链接获取数据,同时存储在 Scrapy 中的一项中

Posted

技术标签:

【中文标题】从多个链接获取数据,同时存储在 Scrapy 中的一项中【英文标题】:Taking data from multiple links while storing in one item in Scrapy 【发布时间】:2016-02-03 21:50:00 【问题描述】:

我目前正在通过 Scraby 学习网络抓取的基础知识,并且遇到了一个特定的问题,即项目被复制而不是扩展。

我从其中抓取数据的第一页有一些链接,我需要按照这些链接来抓取其他链接。这些链接存储为 item['link']。

我的问题是,通过嵌套在循环中的请求遍历这些链接,结果不会附加到原始项目实例,而是作为新实例返回。

因此结果如下所示:

'date': [u'29 June 2015', u'15 September 2015'],
'desc': [u'Audit Committee - 29 June 2015',
      u'Audit Committee - 15 September 2015'],
'link': [u'/Council/Council-and-Committee-Minutes/Audit-Committee/2015/Audit-Committee-29-June-2015',
      u'/Council/Council-and-Committee-Minutes/Audit-Committee/2015/Audit-Committee-15-September-2015'],
'pdf_url': 'http://www.antrimandnewtownabbey.gov.uk/Council/Council-and-Committee-Minutes/Audit-Committee/2015/Audit-Committee-15-September-2015',
'title': [u'2015']

'date': [u'29 June 2015', u'15 September 2015'],
'desc': [u'Audit Committee - 29 June 2015',
      u'Audit Committee - 15 September 2015'],
'link': [u'/Council/Council-and-Committee-Minutes/Audit-Committee/2015/Audit-Committee-29-June-2015',
      u'/Council/Council-and-Committee-Minutes/Audit-Committee/2015/Audit-Committee-15-September-2015'],
'pdf_url': 'http://www.antrimandnewtownabbey.gov.uk/Council/Council-and-Committee-Minutes/Audit-Committee/2015/Audit-Committee-29-June-2015',
'title': [u'2015']

我希望它们包含在同一个对象中,如下所示:

'date': [u'29 June 2015', u'15 September 2015'],
'desc': [u'Audit Committee - 29 June 2015',
      u'Audit Committee - 15 September 2015'],
'link': [u'/Council/Council-and-Committee-Minutes/Audit-Committee/2015/Audit-Committee-29-June-2015',
      u'/Council/Council-and-Committee-Minutes/Audit-Committee/2015/Audit-Committee-15-September-2015'],
'pdf_url': [u'http://www.antrimandnewtownabbey.gov.uk/Council/Council-and-Committee-Minutes/Audit-Committee/2015/Audit-Committee-29-June-2015',
      u'http://www.antrimandnewtownabbey.gov.uk/Council/Council-and-Committee-Minutes/Audit-Committee/2015/Audit-Committee-15-September-2015'],
'title': [u'2015']

这是我当前的实现(主要基于 Scrapy 教程):

def parse(self, response):
    for sel in response.xpath('//div[@class="lower-col-right"]'):
        item = CouncilExtractorItem()
        item['title'] = sel.xpath('header[@class="intro user-content font-set clearfix"] /h1/text()').extract()
        item['link'] = sel.xpath('div[@class="user-content"] /section[@class="listing-item"]/a/@href').extract()
        item['desc'] = sel.xpath('div[@class="user-content"] /section[@class="listing-item"]/a/h2/text()').extract()
        item['date'] = sel.xpath('div[@class="user-content"] /section[@class="listing-item"]/span/text()').extract()
        for url in item['link']:
            full_url = response.urljoin(url)
            request = scrapy.Request(full_url, callback=self.parse_page2)
            request.meta['item'] = item
            yield request

def parse_page2(self, response):
    item = response.meta['item']
    item['pdf'] = response.url
    return item

【问题讨论】:

【参考方案1】:

您需要通过在前面添加一个点来使您的内部 XPath 表达式特定于上下文

for sel in response.xpath('//div[@class="lower-col-right"]'):
    item = CouncilExtractorItem()
    item['title'] = sel.xpath('.//header[@class="intro user-content font-set clearfix"]/h1/text()').extract()
    item['link'] = sel.xpath('.//div[@class="user-content"]/section[@class="listing-item"]/a/@href').extract()
    item['desc'] = sel.xpath('.//div[@class="user-content"]/section[@class="listing-item"]/a/h2/text()').extract()
    item['date'] = sel.xpath('.//div[@class="user-content"]/section[@class="listing-item"]/span/text()').extract()
    # ...

【讨论】:

我试了一下,但我的代码肯定有其他问题导致了这个问题。 @user5520937 你确定你在每个内部 xpath 的开头都尝试过 .// 吗? 是的 - 这是我遇到的最后一个问题 - 感谢您指出这一点【参考方案2】:

问题是以下两块代码一起工作的组合:

    for url in item['link']:
        full_url = response.urljoin(url)
        request = scrapy.Request(full_url, callback=self.parse_page2)
        request.meta['item'] = item
        yield request

    def parse_page2(self, response):
        item = response.meta['item']
        item['pdf'] = response.url
        return item

您正在使用 item 作为每个 URL 的元元素创建新请求,然后您将替换该项目的“pdf”字段,然后生成该项目。最终结果:对于每个 URL,您都会获得一个具有不同 PDF 字段的新重复项。

目前,Scrapy 无法知道您打算如何处理该项目。您需要将代码更改为:A) 跟踪所有 URL,并且仅在处理完所有 URL 后才生成,B) 附加到 item['pdf'],而不是覆盖它。

【讨论】:

以上是关于从多个链接获取数据,同时存储在 Scrapy 中的一项中的主要内容,如果未能解决你的问题,请参考以下文章

HTTP POST 和使用 Scrapy 解析 JSON

Scrapy爬取全站数据并存储到数据库和文件中

Scrapy中如何获取下一页链接

使用 Scrapy 从 HTML 中的 <script> 标签获取数据

用于从具有多个条件的多个表中的多个列中获取数据的存储过程

Spider使用scrapy运行,但没有数据存储到csv中