【问题标题】:Selecting the text contents in a particular <div> that has another <div> within it using Scrapy and Xpath使用 Scrapy 和 Xpath 选择包含另一个 <div> 的特定 <div> 中的文本内容
【发布时间】:2014-10-09 17:18:17
【问题描述】:

编辑:解决了!对于那些在学习中遇到这种情况的人;答案在下面,由 Paul 很好地解释和提供。

这是我在这里的第一个问题,我已经搜索和搜索(到目前为止两天)无济于事。我正在尝试抓取特定的零售网站以获取产品名称和价格。

目前,我有一个蜘蛛在一个特定的零售网站上工作,但是,在另一个零售网站上,它有点工作。我可以正确获取产品名称,但无法获取正确格式的价格。

首先,这是我目前的蜘蛛代码:

import scrapy

from projectname.items import projectItem

class spider_whatever(scrapy.Spider):
    name = "whatever"
    allowed_domain = ["domain.com"]
    start_urls = ["http://www.domain.com"]

    def parse(self, response):
        sel = scrapy.Selector(response)
        requests = sel.xpath('//div@class="container"]')
        product = requests.xpath('.//*[@class="productname"/text()]').extract()
        price = requests.xpath('.//*[@class="price"]').extract() #Issue lies here.

        itemlist = []
        for product, price in zip(product, price):
            item = projectItem()
            item['product'] = product.strip().upper()
            item['price'] = price.strip()
            itemlist.append(item)
        return itemlist

现在价格的目标 HTML 是:

<div id="listPrice1" class="price">
                        $622                        <div class="cents">.00</div>
                    </div>

如您所见,它不仅杂乱无章,而且在我要引用的 div 中还有一个 div。现在当我去尝试这样做时:

price = requests.xpath('.//*[@class="price"]/text()').extract()

它吐出这个:

product,price
some_product1, $100
some_product2, 
some_product3, $200
some_product4, 

什么时候应该吐出来:

product,price
some_product1, $100
some_product2, $200
some_product3, $300
some_product4, $400

我认为它正在做的是;它还提取 div class="cents" 并将其分配给下一个产品,因此将下一个值向下推。

当我尝试通过 Google Docs 电子表格抓取数据时,它会将产品放在一列中,而价格分为两列;第一个是 $ 金额,第二个是 .00 美分,如下所示:

product,price,cents
some_product1, $100, .00
some_product2, $200, .00
some_product3, $300, .00
some_product4, $400, .00

所以我的问题是,如何将 div 中的 div 分开。有没有一种特殊的方法可以将它从 XPath 中排除,或者我可以在解析数据时将其过滤掉?如果我可以过滤掉它,我该怎么做?

非常感谢任何帮助。请理解,我对 Python 比较陌生,正在努力学习。

【问题讨论】:

    标签: python html xpath web-scraping scrapy


    【解决方案1】:

    让我们探索几种不同的 XPath 模式:

    >>> import scrapy
    >>> selector = scrapy.Selector(text="""<div id="listPrice1" class="price">
    ...                         $622                        <div class="cents">.00</div>
    ...                     </div>""")
    
    # /text() will select all text nodes under the context not,
    # here any element with class "price"
    # there are 2 of them
    >>> selector.xpath('.//*[@class="price"]/text()').extract()
    [u'\n                        $622                        ', u'\n                    ']
    
    # if you wrap the context node inside the "string()" function,
    # you'll get the string representation of the node,
    # basically a concatenation of text elements
    >>> selector.xpath('string(.//*[@class="price"])').extract()
    [u'\n                        $622                        .00\n                    ']
    
    # using "normalize-space()" instead of "string()",
    # it will replace multiple space with 1 space character
    >>> selector.xpath('normalize-space(.//*[@class="price"])').extract()
    [u'$622 .00']
    
    # you could also ask for the 1st text node under the element with class "price"
    >>> selector.xpath('.//*[@class="price"]/text()[1]').extract()
    [u'\n                        $622                        ']
    
    # space-normalized version of that may do what you want
    >>> selector.xpath('normalize-space(.//*[@class="price"]/text()[1])').extract()
    [u'$622']
    >>> 
    

    所以,最终,你可能会遵循这种模式:

    def parse(self, response):
        sel = scrapy.Selector(response)
        requests = sel.xpath('//div@class="container"]')
        itemlist = []
        for r in requests:
            item = projectItem()
            item['product'] = r.xpath('normalize-space(.//*[@class="productname"])').extract()
            item['price'] = r.xpath('normalize-space(.//*[@class="price"]/text()[1])').extract()
            itemlist.append(item)
        return itemlist
    

    【讨论】:

    • 你是绝对的冠军!我不知道你可以选择特定的文本节点!这太棒了!谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-01
    • 2013-02-13
    • 2015-10-16
    相关资源
    最近更新 更多