【问题标题】:Scrapy - Grabbing Multiple ItemsScrapy - 抓取多个物品
【发布时间】:2016-02-13 04:34:55
【问题描述】:

scrapy 新手,请多多包涵。

首先,这是我的代码:

from scrapy.spider     import BaseSpider
from scrapy.selector     import HtmlXPathSelector
from usdirectory.items    import UsdirectoryItem
from scrapy.http    import Request


class MySpider(BaseSpider):
    name         = "usdirectory"
    allowed_domains    = ["domain.com"]
    start_urls    = ["url_removed_sorry"]

    def parse(self, response):
        hxs     = HtmlXPathSelector(response)
        titles     = hxs.select('//*[@id="holder_result2"]/a[1]/span/span[1]/text()').extract()
        for title in titles:
                item = UsdirectoryItem()
                item["title"] = title
                item


        yield item

这行得通...但它只抓取第一个项目。

我注意到在我试图抓取的项目中,每行的 Xpath 都会发生变化。例如,第一行是您在上面看到的 xpath:

//*[@id="holder_result2"]/a[1]/span/span[1]/text()

然后它增加 2,一直到 29。所以第二个结果:

//*[@id="holder_result2"]/a[3]/span/span[1]/text()

最后结果:

//*[@id="holder_result2"]/a[29]/span/span[1]/text()

所以我的问题是如何让脚本获取所有这些,我不在乎是否必须为每个项目复制和粘贴代码。所有其他页面完全相同。我只是不知道该怎么做。

非常感谢。

编辑:

import scrapy
from scrapy.item import Item, Field

class UsdirectoryItem(scrapy.Item):
    title = scrapy.Field()

【问题讨论】:

  • 这可能是您问题中的代码格式问题,但一个问题是“yield item”需要在“for title”循环内。仅在“解析”结束时产生一个收益,您只会得到 1 项返回

标签: python xpath web-scraping scrapy


【解决方案1】:

鉴于模式与您描述的完全一样,您可以在 a 的位置索引上使用 XPath modulo operator mod 来获取所有目标 a 元素:

//*[@id="holder_result2"]/a[position() mod 2 = 1]/span/span[1]/text()

为了快速演示,请考虑以下输入 XML:

<div>
 <a>1</a>
 <a>2</a>
 <a>3</a>
 <a>4</a>
 <a>5</a>
</div>

鉴于此 XPath /div/a[position() mod 2 = 1],将返回以下元素:

<a>1</a>
<a>3</a>
<a>5</a>

在 xpathtester.com here 中查看现场演示

【讨论】:

  • 好的,当我放入那个 xpath 时,它只抓取最后一条记录,而不是中间的任何东西。想法?
  • @dkeeper09 问题几乎可以肯定是您没有显示输入文档。
  • 好的,看看原帖,看看是不是你要找的。​​span>
  • @dkeeper09 不怕。输入文档是指我们可以用来重现您的问题的 HTML 源文档。如果它太大,则显示其中重要的相关部分。
  • 哦,你是说我要抓取的页面的来源?
【解决方案2】:

让我知道这是否适合您。请注意,我们正在迭代 a[i] 而不是 a[1]。结果存储在一个列表中(希望如此)。

def parse(self, response):
    hxs = HtmlXPathSelector(response)

    for i in xrange(15):
        titles = hxs.select('//*[@id="holder_result2"]/a[' + str(1+i*2) + ']/span/span[1]/text()').extract()
        for title in titles:
                item = UsdirectoryItem()
                item["title"] = title
                item #erroneous line?
        items.append(item)
        yield item

【讨论】:

  • 我在这方面遇到了一大堆错误,但我将尝试修改代码,看看能否让它工作。
  • 请不要用未经测试的代码提交答案,如果你不确定你的代码是做什么的,那它是没有用的。 for i in xrange(15) 确实 not 返回 1,3,5... 并且 i 未插入到 XPath 字符串中。
  • 感谢@Mathias-Müller。没有复制我的部分代码。在我睡眠不足的状态下,我还以某种方式期望“i”被插入。 dkeeper09:你的工作顺利吗?
  • 不,这不起作用:/它没有给我任何结果。
  • 谢谢。我将生成一些虚拟页面进行测试。我可能需要一两天才能完成。
猜你喜欢
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-24
相关资源
最近更新 更多