如果我尝试下载 https://www.conrad.ch/de/p/42105-lego-technic-katamaran-2255199.html 的 HTML 代码来解析价格。但是,我得到的代码与浏览器中的代码完全不同。
from bs4 import BeautifulSoup
import requests
url_front = requests.get("https://www.conrad.ch/de/p/42105-lego-technic-katamaran-2255199.html").text
front = BeautifulSoup(url_front, "lxml")
front.find("div", id="productPrice").text
AttributeError: 'NoneType' object has no attribute 'text'
在下载的代码中我什至没有找到“价格”一词。
不知道这是否与 iframe、Javascript 有关...?我不喜欢网络开发,所以我不知道从哪里开始找到错误......
有人可以帮忙吗?
此页面是通过 JavaScript 使用 XHR 呈现的。好消息是您可以访问与 JavaScript 直接访问相同的 API。
import requests
import json
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json;charset=UTF-8'
}
params = (
('apikey', '1Ikv5R4JFlk6MYIFlBAMSgH1cbvzWdzk'),
('overrideCalculationSchema', 'GROSS'),
)
data = '{"ns:inputArticleItemList":{"#namespaces":{"ns":"http://www.conrad.de/ccp/basit/service/article/priceandavailabilityservice/api"},"articles":[{"articleID":"2255199","insertCode":"62","checkAvailability":true,"calculatePrice":true,"findExclusions":true}]}}'
j = requests.post('https://api.conrad.ch/price-availability/4/CQ_CH_B2C/facade', headers=headers, params=params, data=data).json()
# Uncomment the next line to see the JSON object
# print(json.dumps(j, indent=4))
price_elem = j['priceAndAvailabilityFacadeResponse']['priceAndAvailability']['price']
print(price_elem['price'], price_elem['currency'])
输出
38.95 CHF
在禁用 JavaScript 的情况下在浏览器中打开 URI 会留下一个相当空的页面。这是由于 JavaScript 没有“设置”页面。
如果您运行的是安装了
curl
的 Linux 或 Mac,请尝试在终端中运行此命令:
curl https://www.conrad.ch/de/p/42105-lego-technic-katamaran-2255199.html | grep productPrice
您会看到那里的页面确实没有根据请求提供
productPrice
元素。解决这个问题的方法是使用 Selenium
(查看文档)。简而言之,它就像一个浏览器,能够完全加载页面,然后您可以查询页面上的 JavaScript 在初始页面加载后插入的元素。
我猜测您正在查找的数据是在页面加载后由 JavaScript 加载的。然后,您可以使用诸如
Selenium
之类的包来获取数据,该包驱动您的浏览器(本例中为 Chrome),如下所示:
from selenium import webdriver
from bs4 import BeautifulSoup
options = webdriver.ChromeOptions()
options.add_argument("headless")
options.add_experimental_option('excludeSwitches', ['enable-logging'])
driver = webdriver.Chrome(options=options)
driver.implicitly_wait(10)
try:
driver.get('https://www.conrad.ch/de/p/42105-lego-technic-katamaran-2255199.html')
elem = driver.find_element_by_id('productPrice') # wait for up to 10 seconds for this id to appear
front = BeautifulSoup(driver.page_source, 'lxml')
print(front.find("div", id="productPrice").text)
finally:
driver.quit()
打印:
-26 %
CHF 52.95
CHF 38.95