用硒刮

时间:2020-06-02 19:16:16

标签: python-3.x selenium selenium-webdriver web-scraping beautifulsoup

您好,我想抓取我最初使用Bs4的该网站,可以很好地获取某些元素。部门,名称等。但是我无法使用它来获取财务数据。下面我复制了一些page_source,在这种情况下,“-”应为0.0663。我相信我正在尝试抓取javascript,并且四处张望,没有看到的解决方案对我有用。我想知道是否有人可以帮助我解决这个问题。

尽管我将不胜感激,如果有人可以发布一些有效的代码,如果您也能指出正确的方向,以了解在html中寻找的内容,我将不胜感激,该内容向我展示了我需要做什么以及如何做得到它有点东西。

URL:https://www.tradingview.com/symbols/LSE-TSCO/

HTML:

<span class="tv-widget-fundamentals__label apply-overflow-tooltip">
    Return on Equity (TTM)
</span>
<span class="tv-widget-fundamentals__value apply-overflow-tooltip">
    —
</span>

Python代码:

url = "https://www.tradingview.com/symbols/LSE-TSCO/"
options = webdriver.ChromeOptions()
options.add_argument('headless')
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get(url)
html = driver.page_source

3 个答案:

答案 0 :(得分:2)

要获取净值,请诱发WebDriverWait()并等待visibility_of_element_located()并位于xpath以下。

driver.get(url)
print(WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.XPATH,"//span[contains(.,'Return on Equity (TTM)')]/following-sibling::span[1]"))).text)

您需要导入以下库。

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

答案 1 :(得分:1)

您可以使用xpath

获得股本回报率
equity = driver.find_element_by_xpath('/html/body/div[2]/div[4]/div/div/div/div/div/div[2]/div[2]/div[2]/div/div[2]/div[1]/div/div/div[1]/div[3]/div[3]/span[2]').text
print(equity)

答案 2 :(得分:0)

这里的问题不是元素是否存在,而是页面加载所需的时间。所有这些动态图的页面看起来都很沉重。即使在完全加载页面之前,也开始创建DOM并使用默认值。

WebDriverWaitfind_element_*可以在当前不存在该元素但需要一定时间才能显示时使用。在您的上下文中,它从一开始就存在,并且添加不会有多大作用。这也是为什么得到“-”的原因,因为该元素以其默认值存在。

要解决此问题或减少问题,您可以添加代码以等待文档readyState完成

可以使用以下方法:

def wait_for_page_ready_state(driver):
    wait = WebDriverWait(driver, 20)

    def _ready_state_script(driver):
        return driver.execute_async_script(
                """
                var callback = arguments[arguments.length - 1]; 
                callback(document.readyState);
                """) == 'complete'
    wait.until(_ready_state_script)

wait_for_page_ready_state(driver)

然后,由于您将bs4引入游戏中,因此我将在这里使用它:

financials = {}
for el in BeautifulSoup(driver.page_source, "lxml").find_all('div', {"class": "tv-widget-fundamentals__row"}):
    try:
        key = re.sub('\s+', ' ', el.find('span', {"class": "tv-widget-fundamentals__label "
                                                       "apply-overflow-tooltip"}).text.strip())
        value = re.sub('\s+', ' ', el.find('span', {"class": "tv-widget-fundamentals__value"}).text.strip())


        financials[key] = value
    except AttributeError:
        pass

这将为您提供金融卡所需的一切价值。

您现在可以打印所需的值:

print(financials['Return on Equity (TTM)'])

输出:

'0.0663'

当然,您也可以对硒进行上述操作,但希望提供您开始使用的硒。

要注意,这并不保证总是返回正确的值。在我的情况下可能会这样做,但是由于您知道默认值,因此可以添加一个while循环,直到默认更改为止。

[编辑] 循环运行代码后,我达到默认值1/5倍。解决该问题的一种方法是创建一个方法并循环直到达到阈值。在我的发现中,您将始终用数字更新约90%的值。如果使用默认值失败,则所有其他值也都位于“-”。一种方法是使用阈值(即50%,并且仅在达到阈值时才返回值)。

    def get_financial_card_values(default_value='—', threshold=.5):
        financials = {}
        while True:
            for el in BeautifulSoup(driver.page_source, "lxml").find_all('div', {"class": "tv-widget-fundamentals__row"}):
                try:
                    key = re.sub('\s+', ' ', el.find('span', {"class": "tv-widget-fundamentals__label "
                                                                       "apply-overflow-tooltip"}).text.strip())
                    value = re.sub('\s+', ' ', el.find('span', {"class": "tv-widget-fundamentals__value"}).text.strip())

                    financials[key] = value
                except AttributeError:
                    pass
            number_of_updated_values = [value for value in financials.values() if value != default_value]
            if len(number_of_updated_values) / len(financials) > threshold:
                return financials

使用这种方法,我能够始终检索您期望的值。请注意,如果所有值都不会改变(站点问题),则您将永远处于循环中,您可能希望使用计时器而不是while True。只是想指出这一点,但我认为它不会发生。