我对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;打印所有品牌运行。
我真的很感激有任何帮助来解决这个问题。
非常感谢。
答案 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()