数据表的 Scrapy xpath 构造 - 产生空括号
Scrapy xpath construction for tables of data - yielding empty brackets
我正在尝试为我想从站点的数百个页面中提取的数据项构建 xpath 结构,这些页面的格式都相同。示例站点是 https://weedmaps.com/dispensaries/cannabicare
可以看出,该网站有标题,在这些标题中有几行商品名称和价格。我正在尝试提取部分、项目名称和项目价格,无论是每克、8 盎司、每盎司还是食用品的每单位价格,并将它们全部分类。一些 scrapy 项目字段示例如下:
Sativa_Item_Name=scrapy.Field()
Sative_item_price_gra,=scrapy.Field()
Sativa_item_price_eigth=scrapy.Field()
Sativa_item_price_quarter=scrapy.Field()
Edible_Item_Name=scrapy.Field()
Edible_item_Price_Each=scrapy.Field()
依此类推。我能够使用 xpaths 提取所有项目名称和所有 price/gram,如下所示:
response.xpath('.//div/span[@class="item_name"]/text()'].extract()
response.xpath('//div[@data-price-name="price_gram"]/span/text()').extract()
我不知道如何只提取标题容器中的项目,例如仅提取混合类别中项目的每克价格、每个项目的价格和食用类别中的项目名称。
它们是分开的,例如 id="menu_item_category_4" 但是当我做类似的事情时:
response.xpath('//div[@id="menu_item_category_4"]/span[@class="item_name"]/text()').extract()
它产生空括号并且没有结果。对此的任何指导将不胜感激。非常感谢您抽出时间来看这个!
您没有得到任何结果,因为在 div[@id="menu_item_category_4"]
和 span[@class="item_name"]
之间您只有 /
,这意味着 span
必须是div
。在它们之间使用 //
,这样 span
可以是 div
.
的任何后代
查看 Chrome 中的 DOM 树,我看到 div[@id="menu_item_category_1"]
和 span[@class="item_name"]
之间大约有六层 div
后代。
问题是您在浏览器中看到的是 在 Javascript 格式化后,大概是 Angular.
如果您 运行 a HTML source beautifier 中的 HTML 来源并搜索 <span class="item_name">
您将看到这样的模式,重复
<div class="menu_item" data-category-id="1" data-category-name="Indica" data-json="{}" id="menu_item_5390083" style="position: relative; overflow: visible;">
<div class="js-edit"><a class="btn" href="/new_admin/dispensaries/cannabicare/menu_items/banana-og-member-pricing/edit"><i class="icon-edit">Edit</i></a></div>
<div class="menu-item-form-container js-form" style="display: none;"></div>
<div class="menu-item-content js-content">
<div class="row">
<div class="col-md-4 name"><span class="item_name">Banana OG - Member Pricing</span></div>
<div class="col-md-8 js-prices prices menu-item-prices">
<div class="col-sm-2 col-md-2 price-container" data-price-name="price_gram"><span class="price">9 </span><span class="price-label">g</span></div>
<div class="col-sm-2 col-md-2 price-container" data-price-name="price_eighth"><span class="price">30 </span><span class="price-label">1/8</span></div>
<div class="col-sm-2 col-md-2 price-container" data-price-name="price_quarter"><span class="price">60 </span><span class="price-label">1/4</span></div>
<div class="col-sm-2 col-md-2 price-container" data-price-name="price_half_ounce"><span class="price">90 </span><span class="price-label">1/2</span></div>
<div class="col-sm-2 col-md-2 price-container" data-price-name="price_ounce"><span class="price">165 </span><span class="price-label">oz</span></div>
</div>
</div>
<div class="row item-options" style="display: none;">
<div class="col-md-3 text"></div>
<div class="col-md-2 category-id">
<div class="category-id-select" style="display: none;"></div>
</div>
<div class="current-category-id" id="current-category-menu-item-5390083" style="display: none;">1</div>
</div>
<div class="row">
<div class="col-md-12 dispensary_name"><a href="/dispensaries/cannabicare">Cannabicare</a></div>
</div>
<div style="height:1px"></div>
<div class="row item_details">
<div class="col-md-10">75% Indica / 25% Sativa</div>
</div>
</div>
</div>
这是您需要处理的HTML。
你可以使用类似的方法提取数据:
for category in response.css('div.menu_item'):
print "--- Category:", category.xpath('@data-category-name').extract()
for row in category.css('div.menu-item-content > div.row:first-child'):
print row.xpath('string(.//span[@class="item_name"])').extract()
for price in row.css('div.prices > div.price-container'):
print "Price:", price.xpath('@data-price-name').extract(), price.css('span.price::text').extract()
输出:
--- Category: [u'Indica']
[u'Banana OG - Member Pricing']
Price: [u'price_gram'] [u'9 ']
Price: [u'price_eighth'] [u'30 ']
Price: [u'price_quarter'] [u'60 ']
Price: [u'price_half_ounce'] [u'90 ']
Price: [u'price_ounce'] [u'165 ']
--- Category: [u'Indica']
[u'Purple Kush - Member Pricing']
Price: [u'price_gram'] [u'9 ']
Price: [u'price_eighth'] [u'30 ']
Price: [u'price_quarter'] [u'60 ']
Price: [u'price_half_ounce'] [u'90 ']
Price: [u'price_ounce'] [u'165 ']
...
我正在尝试为我想从站点的数百个页面中提取的数据项构建 xpath 结构,这些页面的格式都相同。示例站点是 https://weedmaps.com/dispensaries/cannabicare
可以看出,该网站有标题,在这些标题中有几行商品名称和价格。我正在尝试提取部分、项目名称和项目价格,无论是每克、8 盎司、每盎司还是食用品的每单位价格,并将它们全部分类。一些 scrapy 项目字段示例如下:
Sativa_Item_Name=scrapy.Field()
Sative_item_price_gra,=scrapy.Field()
Sativa_item_price_eigth=scrapy.Field()
Sativa_item_price_quarter=scrapy.Field()
Edible_Item_Name=scrapy.Field()
Edible_item_Price_Each=scrapy.Field()
依此类推。我能够使用 xpaths 提取所有项目名称和所有 price/gram,如下所示:
response.xpath('.//div/span[@class="item_name"]/text()'].extract()
response.xpath('//div[@data-price-name="price_gram"]/span/text()').extract()
我不知道如何只提取标题容器中的项目,例如仅提取混合类别中项目的每克价格、每个项目的价格和食用类别中的项目名称。
它们是分开的,例如 id="menu_item_category_4" 但是当我做类似的事情时:
response.xpath('//div[@id="menu_item_category_4"]/span[@class="item_name"]/text()').extract()
它产生空括号并且没有结果。对此的任何指导将不胜感激。非常感谢您抽出时间来看这个!
您没有得到任何结果,因为在 div[@id="menu_item_category_4"]
和 span[@class="item_name"]
之间您只有 /
,这意味着 span
必须是div
。在它们之间使用 //
,这样 span
可以是 div
.
查看 Chrome 中的 DOM 树,我看到 div[@id="menu_item_category_1"]
和 span[@class="item_name"]
之间大约有六层 div
后代。
问题是您在浏览器中看到的是 在 Javascript 格式化后,大概是 Angular.
如果您 运行 a HTML source beautifier 中的 HTML 来源并搜索 <span class="item_name">
您将看到这样的模式,重复
<div class="menu_item" data-category-id="1" data-category-name="Indica" data-json="{}" id="menu_item_5390083" style="position: relative; overflow: visible;">
<div class="js-edit"><a class="btn" href="/new_admin/dispensaries/cannabicare/menu_items/banana-og-member-pricing/edit"><i class="icon-edit">Edit</i></a></div>
<div class="menu-item-form-container js-form" style="display: none;"></div>
<div class="menu-item-content js-content">
<div class="row">
<div class="col-md-4 name"><span class="item_name">Banana OG - Member Pricing</span></div>
<div class="col-md-8 js-prices prices menu-item-prices">
<div class="col-sm-2 col-md-2 price-container" data-price-name="price_gram"><span class="price">9 </span><span class="price-label">g</span></div>
<div class="col-sm-2 col-md-2 price-container" data-price-name="price_eighth"><span class="price">30 </span><span class="price-label">1/8</span></div>
<div class="col-sm-2 col-md-2 price-container" data-price-name="price_quarter"><span class="price">60 </span><span class="price-label">1/4</span></div>
<div class="col-sm-2 col-md-2 price-container" data-price-name="price_half_ounce"><span class="price">90 </span><span class="price-label">1/2</span></div>
<div class="col-sm-2 col-md-2 price-container" data-price-name="price_ounce"><span class="price">165 </span><span class="price-label">oz</span></div>
</div>
</div>
<div class="row item-options" style="display: none;">
<div class="col-md-3 text"></div>
<div class="col-md-2 category-id">
<div class="category-id-select" style="display: none;"></div>
</div>
<div class="current-category-id" id="current-category-menu-item-5390083" style="display: none;">1</div>
</div>
<div class="row">
<div class="col-md-12 dispensary_name"><a href="/dispensaries/cannabicare">Cannabicare</a></div>
</div>
<div style="height:1px"></div>
<div class="row item_details">
<div class="col-md-10">75% Indica / 25% Sativa</div>
</div>
</div>
</div>
这是您需要处理的HTML。
你可以使用类似的方法提取数据:
for category in response.css('div.menu_item'):
print "--- Category:", category.xpath('@data-category-name').extract()
for row in category.css('div.menu-item-content > div.row:first-child'):
print row.xpath('string(.//span[@class="item_name"])').extract()
for price in row.css('div.prices > div.price-container'):
print "Price:", price.xpath('@data-price-name').extract(), price.css('span.price::text').extract()
输出:
--- Category: [u'Indica']
[u'Banana OG - Member Pricing']
Price: [u'price_gram'] [u'9 ']
Price: [u'price_eighth'] [u'30 ']
Price: [u'price_quarter'] [u'60 ']
Price: [u'price_half_ounce'] [u'90 ']
Price: [u'price_ounce'] [u'165 ']
--- Category: [u'Indica']
[u'Purple Kush - Member Pricing']
Price: [u'price_gram'] [u'9 ']
Price: [u'price_eighth'] [u'30 ']
Price: [u'price_quarter'] [u'60 ']
Price: [u'price_half_ounce'] [u'90 ']
Price: [u'price_ounce'] [u'165 ']
...