我正在努力学习如何抓取网站。我使用的是Python3和BS4。
我遇到了一个特定的问题。 例如:http://www2.hm.com/en_in/productpage.0648256001.html
我无法刮掉"尺寸"可在下拉菜单中找到它们是否已售罄,在上面的链接中。我浏览了整个源代码,但无法弄清楚数据存在于哪个标签下。我猜它一定是一个隐藏的变量或什么?
答案 0 :(得分:3)
好的,所以我跟踪了网站提出的XHR请求,我编写了下面的代码。基本上,它使用Selenium
来获取productArticleDetails
变量的值和可用性端点的URL(我可以对其进行硬编码,但我找到了它的变量,所以为什么不使用它它)。
from itertools import chain
from urllib.parse import urljoin
import requests
from bs4 import BeautifulSoup
from selenium import webdriver
url = 'http://www2.hm.com/en_in/productpage.0648256002.html'
r = requests.get(url)
soup = BeautifulSoup(r.text, 'lxml')
browser = webdriver.Chrome()
browser.get(url)
details = browser.execute_script('return productArticleDetails;')
availability_url = browser.execute_script('return hm.options.product.productAvailabilityServiceUrl;')
browser.quit()
variants = {} # e.g one product can be available in different colors
for key, value in details.items():
# there is a lot of information in the details, not only product variants
try:
if 'whitePrice' in value:
variants[key] = value
except AttributeError:
pass
# 'http://www2.hm.com/en_in/getAvailability?variants=0648256001,0648256002,0648256003,0648256006,0648256007,0648256008'
payload = {'variants': ','.join(variants.keys())}
r = requests.get(urljoin(url, availability_url), params=payload)
available_sizes = r.json()['availability']
# r.json() contains:
# availability: ["0648256001001", "0648256001002", "0648256001007",…]
# fewPieceLeft: []
sizes = chain.from_iterable(variant['sizes'] for variant in variants.values())
for size in sizes:
availability = size['sizeCode'] in available_sizes
size['available'] = availability # True/False, feel free to implement handling "fewPieceLeft"
# Output
for variant in variants.values():
print(f'Variant: {variant["name"]}') # color in that case
print('\tsizes:')
for size in variant['sizes']:
print(f'\t\t{size["name"]} -> {"Available" if size["available"] else "Sold out"}')
<强>输出:强>
Variant: Light beige/Patterned
sizes:
32 -> Available
34 -> Available
36 -> Sold out
...
Variant: Orange
sizes:
32 -> Available
...
这种方法的优势在于您可以访问许多详细信息,例如'whitePrice': 'Rs. 1,299',
,'careInstructions': ['Machine wash at 30°']
,'composition': ['Viscose 100%']
,说明等等。你可以自己看看:
import pprint
pprint.pprint(variants)
缺点是您需要使用Selenium并下载驱动程序,但公平地说我只使用Selenium来获取变量,因为使用正则表达式提取这个嵌套的JS对象对我来说似乎是不可能的(如果我&#39;我错了)browser.execute_script('return productArticleDetails;')
非常简洁明了。
没有隐藏变量,我们完全有可能获得BeautifulSoup
的尺码,每个尺码为<li>
:
<li class="item" data-code="0648256001002">
<div class="picker-option"><button type="button" class="option"><span class="value">34</span></button></div>
</li>
您需要将尺寸的data-code
属性与&#34;产品变体&#34;的data-articlecode
属性相匹配:
<li class="list-item">
<a title="Light beige/Patterned" data-color="Light beige/Patterned"
data-articlecode="0648256001">
...
</a>
</li>
我鼓励您自己实施,但我会在晚上/明天尝试对其进行编码以完成答案。但是,该网站使用JavaScript呈现,并且在对GET请求的响应中,您不会获得您在DevTools的Elements选项卡中看到的整个HTML。您可以使用Selenium来做到这一点,但就个人而言,我使用Requests-HTML