关于美汤4模块的问题

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

我很困惑,因为这段代码有时有效,有时无效。该代码基于美丽的汤模块。我想知道为什么它在某些情况下有效,而在其他情况下为什么无效。

from bs4 import BeautifulSoup
import requests
import lxml
import pandas as pd

url = "https://coinmarketcap.com/currencies/xrp/"
request = requests.get(url)
content = request.text
soup = BeautifulSoup(content, "lxml")

res = soup.find('div', class_=["priceSection"])
price = res.find('div', class_=["priceValue"])
title = res.find('div', class_=["priceTitle"])
result = title.text.replace(price.text,'')
print(result)
python parsing beautifulsoup python-requests lxml
2个回答
0
投票

使用

Javascript
在网页中实时更新数据,这似乎是问题所在。
为此,您可以尝试使用 selenium

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
driver.get('https://coinmarketcap.com/currencies/xrp/')
wait = WebDriverWait(driver, 5)
data = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '.bIyrLx')))
print(data.text)
driver.quit()

0
投票

从错误消息中,您了解到问题来自

res
being
None
。发生这种情况是因为
soup.find('div', class_=["priceSection"])
没有找到任何东西(此行为已明确记录

您的代码有时有效有时无效的最明显原因是网站并不总是对您的请求返回相同的响应。

最简单(虽然不是最干净)的修复方法是在使用之前检查您是否确实得到了结果 (

if res is not None:
)。然后,如果您的
None
呼叫得到
find(...)
结果,您将能够做一些适当的事情,例如等待几秒钟并重试请求。

如果你想要一种更简洁的方式让你的代码更可靠,你可以将请求和解析包装成一个函数:

from bs4 import BeautifulSoup
import requests
import lxml
import time

def get_price(currency, max_retries=5, wait_s=2):
    url = f"https://coinmarketcap.com/currencies/{currency}/"
    request = requests.get(url)
    content = request.text
    soup = BeautifulSoup(content, "lxml")
    
    res = soup.find('div', class_=["priceSection"])
    if res is not None:
        price = res.find('div', class_=["priceValue"])
        title = res.find('div', class_=["priceTitle"])
        result = title.text.replace(price.text,'')
    elif max_retries > 0:
        print(f"Waiting {wait_s}s before retrying ({max_retries} tries left)")
        time.sleep(wait_s)
        result = get_price(currency, max_retries=max_retries-1, wait_s=wait_s*2)
    else:
        print(f"Could not find a 'div.priceSection' in :\n{content}")
        result = "Error : Max retries exceeded"
    
    return result

print(get_price("xrp"))

您正在抓取的网站 (Coinmarketcap) 似乎是一个单页应用程序 (SPA),在第一次加载时具有服务器端渲染 (SSR)。当您第一次加载页面时,SSR 会在服务器上执行 javascript,并直接为您提供呈现的 HTML。如果没有 SSR,你的爬虫将需要自己执行 Javascript 才能工作。

在测试我刚刚提供的代码后,Coinmarketcap 似乎在你向它发出大量请求后禁用了 SSR,可能是为了防止你在他们的服务器上使用太多资源。这不会阻止页面在常规浏览器中工作,因为 SPA 仍在提供服务,但会阻止大多数机器人和爬虫,例如您问题中的简单机器人。您应该尝试在每个请求之间添加几秒钟的延迟,以便首先不触发机器人检测。

© www.soinside.com 2019 - 2024. All rights reserved.