【问题标题】:How to loop from a list of urls by clicking the xpath and extract data using Selenium in Python?如何通过单击 xpath 从 url 列表中循环并在 Python 中使用 Selenium 提取数据?
【发布时间】:2019-10-15 15:19:55
【问题描述】:

我正在从 URL 列表中提取董事会成员。对于 URL_lst 中的每个 url,单击第一个 xpath(查看更多以展开列表),然后从第二个 xpath(BoardMembers 的信息)中提取值。 以下是我要提取信息的三个公司:https://www.bloomberg.com/quote/FB:UShttps://www.bloomberg.com/quote/AAPL:UShttps://www.bloomberg.com/quote/MSFT:US

我的代码如下所示,但不起作用。输出列表未聚合。我知道循环有问题,但不知道如何修复它。谁能告诉我如何更正代码?谢谢!

URL_lst = ['https://www.bloomberg.com/quote/FB:US','https://www.bloomberg.com/quote/AAPL:US','https://www.bloomberg.com/quote/MSFT:US']

Outputs = []
driver = webdriver.Chrome(r'xxx\chromedriver.exe')

for url in URL_lst:
    driver.get(url)
    for c in driver.find_elements_by_xpath("//*[@id='root']/div/div/section[3]/div[10]/div[2]/div/span[1]"):
        c.click()
        for e in (c.find_elements_by_xpath('//*[@id="root"]/div/div/section[3]/div[10]/div[1]/div[2]/div/div[2]')[0].text.split('\n'):
            Outputs.append(e)

print(Outputs)

【问题讨论】:

  • 您是否在代码中看到错误消息?哪一行特别给你一个错误?发布页面 HTML 以查看您的 XPath 所基于的内容也会很有帮助。

标签: python selenium loops web-scraping


【解决方案1】:

根据您提供的 URL,我为您做了一些重构。我在您尝试单击的每个项目上添加了wait,并通过scrollIntoView Javascript 调用向下滚动到View More 按钮。您最初在循环中单击 View More 按钮,但您的 XPath 仅返回 1 个元素,因此循环是多余的。

我还为董事会成员重构了您的选择器,以直接查询包含其姓名的 div 元素。您的原始查询在实际名称文本上方找到了几个级别的 div,这就是您的 Outputs 列表返回空的原因。

from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from time import sleep

URL_lst = ['https://www.bloomberg.com/quote/FB:US','https://www.bloomberg.com/quote/AAPL:US','https://www.bloomberg.com/quote/MSFT:US']

Outputs = []
driver = webdriver.Chrome(r'xxx\chromedriver.exe')

wait = WebDriverWait(driver, 30)

for url in URL_lst:
    driver.get(url)

    # get "Board Members" header
    board_members_header = wait.until(EC.presence_of_element_located((By.XPATH, "//h2[span[text()='Board Members']]")))

    # scroll down to board members
    driver.execute_script("arguments[0].scrollIntoView();", board_members_header)

    # get view more button
    view_more_button = wait.until(EC.presence_of_element_located((By.XPATH, "//section[contains(@class, 'PageMainContent')]/div/div[2]/div/span[span[text()='View More']]")))

    # click view more button
    view_more_button.click()

    # wait on 'View less' to exist, meaning list is expanded now
    wait.until(EC.presence_of_element_located((By.XPATH, "//section[contains(@class, 'PageMainContent')]/div/div[2]/div/span[span[text()='View Less']]")))


    # wait on visibility of board member names
    wait.until(EC.presence_of_all_elements_located((By.XPATH, "//div[contains(@class, 'boardWrap')]//div[contains(@class, 'name')]")))

    # get list of board members names
    board_member_names = driver.find_elements_by_xpath("//div[contains(@class, 'boardWrap')]//div[contains(@class, 'name')]")

    for board_member in board_member_names:
        Outputs.append(board_member.text)

    # explicit sleep to avoid being flagged as bot
    sleep(5)

print(Outputs)

我还在 URL 抓取之间添加了一个明确的 sleep,这样 Bloomberg 就不会将您标记为机器人。

【讨论】:

  • 谢谢你,克里斯汀!我想知道为什么输出没有汇总?它不会返回这三个公司的所有董事会成员......
  • 您可能需要在整个循环中进行一些检查,以确保 WebElement 被定位。我不喜欢对动态的driver.find_elements 语句使用for,因为您根本不知道是否有任何东西正在迭代。我将重构这段代码以帮助调试它。我还将查看您在问题中包含的链接,看看我是否也可以帮助您的选择器。
  • 非常感谢。我知道“for”循环有问题,但不知道如何解决。
  • @ArthurMorgan 我通过一些重构更新了我的答案。让我知道它是如何为您工作的,我会在最后进行测试。
  • 另外,值得注意的是——在测试时,Bloomberg 确实将我标记为机器人。这不是 Selenium 可以解决的真正问题,只是网站本身实施的一种安全措施。
猜你喜欢
  • 2019-02-16
  • 2019-07-30
  • 2015-01-12
  • 1970-01-01
  • 2021-05-02
  • 2017-04-22
  • 2021-04-02
  • 1970-01-01
  • 2023-02-08
相关资源
最近更新 更多