Scrapy:尝试迭代嵌套项但不产生所需的输出

时间:2017-10-17 03:53:13

标签: python scrapy

我对Python和Scrapy非常陌生,但是当我尝试迭代嵌套的html元素时,它并没有产生预期的结果。

以下是HTML,我正在尝试废弃。

<div class="level1" role="main">
<div class="level2">
    <h1 id="fullStoreHeading" class="class_h1">Page Title</h1>
    <div class="fsdColumn_3">
        <div class='fsdDeptBox'>
            <img alt="" src="" aria-hidden="true" height="100%" width="100%">
            <h2 class="fsdDeptTitle">TV</h2>
            <div class='fsdDeptCol'>
                <a class="class_a" href="/test?_encoding=UTF8&id=1001">Samsung</a>
                <a class="class_a" href="/test?_encoding=UTF8&id=1002">Vizio</a>
                <a class="class_a" href="/test?_encoding=UTF8&id=1003">Element</a>
            </div>
        </div>
        <div class='fsdDeptBox'>
            <img alt="" src="" aria-hidden="true" height="100%" width="100%">
            <h2 class="fsdDeptTitle">Laptop</h2>
            <div class='fsdDeptCol'>
                <a class="class_a" href="/test?_encoding=UTF8&id=1004">Apple</a>
                <a class="class_a" href="/test?_encoding=UTF8&id=1005">Microsoft</a>
                <a class="class_a" href="/test?_encoding=UTF8&id=1006">Dell</a>
            </div>
        </div>
    </div>


    <div class="fsdColumn_3">
        <div class='fsdDeptBox'>
            <img alt="" src="" aria-hidden="true" height="100%" width="100%">
            <h2 class="fsdDeptTitle">Video Game Console</h2>
            <div class='fsdDeptCol'>
                <a class="class_a" href="/test?_encoding=UTF8&id=1007">Xbox One</a>
                <a class="class_a" href="/test?_encoding=UTF8&id=1008">Xbox 360</a>
                <a class="class_a" href="/test?_encoding=UTF8&id=1009">PS 5</a>
            </div>
        </div>
        <div class='fsdDeptBox'>
            <img alt="" src="" aria-hidden="true" height="100%" width="100%">
            <h2 class="fsdDeptTitle">SSD</h2>
            <div class='fsdDeptCol'>
                <a class="class_a" href="/test?_encoding=UTF8&id=1010">Samsung Evo</a>
                <a class="class_a" href="/test?_encoding=UTF8&id=1011">Crucial</a>
                <a class="class_a" href="/test?_encoding=UTF8&id=1012">Sandisk</a>
            </div>
        </div>
    </div>
</div>

我试图从上面的html生成的输出是一个列表:

产品类别 - &gt;品牌 - &gt; ID

E.g。

电视

   Samsung 1001

   Vizio 1002

   Element 1003

笔记本

  Apple 1004

  Microsoft 1005

  Dell 1006

视频游戏控制台

  Xbox Onen 1007

  Xbox 360 1008

  PS4 1009

ProductCategories.py

def parse(self, response):
    l = ItemLoader(item=ProductSpiderItem(), response=response)

    titles = response.xpath('//*[@class="fsdDeptTitle"]')

    for title in titles:

        Product_Category= title.xpath('text()').extract()

        l.add_value('Product_Category', Product_Category)

        for brnd in 
          title.xpath('//*[@class="fsdDeptCol"]/a[@class="class_a"]'):

                Brand = brnd.xpath('text()').extract()
                l.add_value('Brand', Brand)

    return l.load_item()

此时它正在打印所有产品类别来自&#34; Outer For Loop&#34;曾经和&#34; Inner For Loop&#34;正在打印所有品牌,不论产品类别和内部循环&#34;只要&#34;外部循环&#34;打印所有品牌运行。

我真的很感激有任何帮助来解决这个问题。

非常感谢。

2 个答案:

答案 0 :(得分:1)

您的第一个'for'循环将其发送到迭代HTML的<h2 class="fsdDeptTitle">SSD</h2>部分。那么你要做的就是在代码中查找class=class_a。它不能这样做,因为第一个'for'循环太具体了,也无法选择'class_a'所在的HTML。

您可以通过让'for'循环在HTML中看起来更高一级来解决此问题。

titles = response.xpath("//*[@class='fsdDeptBox']")
for title in titles:
    Product_Category=title.xpath('text()').extract()
    l.add_value('Product_Category', Product_Category)

    for brnd in title.xpath('div[@class="fsdDeptCol"]'):
        Brand = brnd.xpath('*/text()').extract()
        l.add_value('Brand', Brand)
    return l.Load_item()

我更改了第一个'for'循环以选择足够的HTML以包含'class_a'文本的路径

旁注。我不太了解正确的HTML术语,但我希望这仍然有意义。

答案 1 :(得分:1)

我认为你应该多查一下ItemLoader的工作原理。它们还取决于您的商品和商品装载机的定义方式,例如我们假设您已定义如下:

class ProductItem(Item):
    category = Field()
    brand = Field()
class ProductItemLoader(ItemLoader):
    default_item_class = ProductItem
    default_output_processor = TakeFirst()
那么你可以这样做:

for product in response.css('.fsdDeptCol a'):
    il = ProductItemLoader(selector=product)
    il.add_xpath('category', './ancestor::*/preceding-sibling::h2/text()')
    il.add_xpath('brand', './text()')
    yield il.load_item()