【问题标题】:Status code 403, not fixable with user agent header状态码 403,无法使用用户代理标头修复
【发布时间】:2021-07-13 06:59:38
【问题描述】:

我正在尝试使用 Python 从网站中提取材料列表的名称和价格。我正在使用下面的代码:

from bs4 import BeautifulSoup
import requests

urls = ['https://www.bricomart.es/materiales-de-construccion/elementos-de-construccion/ladrillos-y-bloques/']

for url in urls:
    headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
    response = requests.get(url, headers=headers)
    soup = BeautifulSoup(response.content, 'html.parser')

    for response in soup.find_all('div', class_='products-list-product'):
        Price = response.p.text
        print(Price)

我正在使用标头,因为如果没有标头,它会给我一个 403 错误。现在我没有收到错误(状态码是 200),但仍然无法获得我需要的信息。运行此代码时我什么也得不到。

有人可以帮忙吗?我更愿意坚持使用 Beautifulsoup 和 requests,因为我对编码的理解非常有限。

谢谢

【问题讨论】:

    标签: python web-scraping beautifulsoup python-requests


    【解决方案1】:

    数据来自 ajax 请求,因此您可以这样调用它:

    import requests
    
    url = "https://www.bricomart.es/rest/V1/products/list/%7B%22page_size%22:20,%22filters%22:%7B%7D,%22order_by%22:%7B%22field%22:%22order%22,%22dir%22:%22ASC%22%7D,%22retailer_id%22:%2272%22,%22category_id%22:%22materiales-de-construccion%252Felementos-de-construccion%252Fladrillos-y-bloques%22,%22page_id%22:1%7D"
    headers={
        "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0",
        "Referer": "https://www.bricomart.es/materiales-de-construccion/elementos-de-construccion/ladrillos-y-bloques/",
        "Authorization": "Bearer lhzi2b9ks5fryccceiby6b1u34v4fe6i",
        "Cookie": "vuex=%7B%22cookies%22%3A%7B%22user%22%3A%7B%22token%22%3A%22%22%2C%22rememberMe%22%3Afalse%2C%22sessionStarted%22%3A%22%22%2C%22isUserPro%22%3Afalse%2C%22allowedSaveCookie%22%3Atrue%7D%2C%22selectedStore%22%3A%7B%22id%22%3A%2272%22%2C%22seller_code%22%3A%22030%22%2C%22name%22%3A%22Bricomart%20Galdakao%22%7D%2C%22isEcommerceActivated%22%3Afalse%7D%7D; datadome=AZTOTNH91rT1ZGLmtYO0SayhnzsesiJ-R3p.5mw8SWra1mJGOy7ugg9rF9Pyqt~aXVdnr5VOsir2WqwgNF-nQmNDUMAnXifm-U0ejpeHyt; _gcl_au=1.1.578284498.1626128324; PHPSESSID=uuukea8g85essiht6nqu0pot3m; t2s-analytics=46bc4ebc-4220-4124-9543-f5f12e4e996a; t2s-p=46bc4ebc-4220-4124-9543-f5f12e4e996a; _ga=GA1.2.802881557.1626128326; _gid=GA1.2.2126596679.1626128326; %40%40=1"
    }
    r = requests.get(url, headers=headers)
    products = r.json()[0]["list"]
    
    for p in products:
        print(p["name"], '||', p["price"], '€')
    

    输出:

    LADRILLO MEGABRICK 70.5X51.5X7 CM TABIQUE || 1.45 €
    LADRILLO RUSTICO ROJO 22.5X11X4CM || 0.27 €
    LADRILLO LISO CLINKER BILBAO ROJO 23.6X11.4X5CM || 0.31 €
    RASILLÓN MACHIHEMBRADO 100X30X4 CM || 0.97 €
    ALBARDILLA CREMA 19X25X6 CM || 0.86 €
    LADRILLO MEGATOSCO 30X19X12 CM || 0.39 €
    LADRILLO TABIQUERO HUECO DOBLE 33X15X7 CM || 0.18 €
    LADRILLO REFRACTARIO 22X11X4 CM || 0.72 €
    LADRILLO PERFORADO 24X11,5X10CM || 0.15 €
    BLOQUE DE HORMIGÓN LISO CREMA 39X19X14 CM || 1.09 €
    BLOQUE DE HORMIGÓN LISO CREMA 39X19X19 CM || 1.32 €
    BLOQUE DE HORMIGÓN GRIS 39X19X14 CM || 0.64 €
    BLOQUE DE HORMIGÓN GRIS 39X19X19 CM || 0.68 €
    BLOQUE LADRILLO TERMOBRICK 30X19X24 CM || 0.79 €
    BLOQUE LADRILLO TERMOBRICK 30X19X19 CM || 0.62 €
    BLOQUE LADRILLO TERMOBRICK 30X19X14 CM || 0.48 €
    BLOQUE DE HORMIGÓN SPLIT MEDIO CREMA 19X19X19 CM || 0.93 €
    BLOQUE DE HORMIGÓN SPLIT ESQUINA CREMA 39X19X19 CM || 1.93 €
    BLOQUE DE HORMIGÓN LISO MEDIO CREMA 19X19X19 CM || 0.83 €
    BLOQUE DE HORMIGÓN LISO 4 CARAS CREMA 39X19X19 CM || 1.48 €
    

    【讨论】:

    • 非常感谢!这正是我需要的!
    • 再次感谢您的解决方案。不过,我有一个后续问题。我注意到输出与网站上显示的不匹配。有时产品和价格不同。你知道为什么会这样吗?另外,您能否指出我可以在哪里了解有关此方法的更多信息?例如,我想知道您是如何提出这些标题的。提前感谢您的帮助!
    【解决方案2】:

    它将无法正常工作,因为您的网站正在动态加载。这意味着在打开页面后,网站会尝试从后端、服务器获取有关材料和价格的信息。当您尝试使用 requests 库时,您会在从服务器加载之前获得一个页面。您需要使用可以在网站上模拟用户的系统。

    如果你想解决这个问题,你需要使用 Selenium 库。该库模仿想要访问该站点的用户。您在 Selenium 上的 bot 可以等到页面加载完毕后再对其进行解析。

    编辑

    例如,如果我们想使用 Google Chrome 浏览器的模拟连接到网站,我们需要使用该代码:

    driver = webdriver.Chrome('path_to_chromedriver')
    driver.get("your_website")
    

    之后,我们需要等待页面何时加载。我们可以使用一个特殊的计时器:

    driver.implicitly_wait(seconds)
    

    或者写一段代码,直到我们需要等待的时刻:

    wait = WebDriverWait(driver, 10)
    element = wait.until(EC.element_to_be_clickable((By.ID, 'someid')))
    

    最后一个 - 我们需要找到一个必需的元素:

    driver.find_element_by_name("your_element") 
    

    使用代码后,您需要使用以下命令关闭 Chrome 驱动程序:

    driver.close()
    

    这些是可以帮助您的主要提示。祝你好运!

    【讨论】:

    • 非常感谢您的详细解释!我对 Selenium 不熟悉,但由于您的指示,它可能可以正常工作。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-12
    • 2018-11-05
    • 2015-07-19
    • 1970-01-01
    • 2014-05-31
    • 2019-07-20
    • 1970-01-01
    相关资源
    最近更新 更多