请求获取的数据与浏览器不同

问题描述 投票:0回答:3

如果我尝试下载 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 有关...?我不喜欢网络开发,所以我不知道从哪里开始找到错误......

有人可以帮忙吗?

python beautifulsoup python-requests
3个回答
2
投票

此页面是通过 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

1
投票

在禁用 JavaScript 的情况下在浏览器中打开 URI 会留下一个相当空的页面。这是由于 JavaScript 没有“设置”页面。

如果您运行的是安装了

curl
的 Linux 或 Mac,请尝试在终端中运行此命令:

curl https://www.conrad.ch/de/p/42105-lego-technic-katamaran-2255199.html | grep productPrice

您会看到那里的页面确实没有根据请求提供

productPrice
元素。解决这个问题的方法是使用
Selenium
(查看文档)。简而言之,它就像一个浏览器,能够完全加载页面,然后您可以查询页面上的 JavaScript 在初始页面加载后插入的元素。


1
投票

我猜测您正在查找的数据是在页面加载后由 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
© www.soinside.com 2019 - 2024. All rights reserved.