使用 Selenium 和 Python 进行动态抓取没有结果

Dynamic scraping with Selenium and Python delivers no results

我正在尝试使用 selenium 抓取以下页面以获取所有工厂的名称:

https://bangladeshaccord.org/factories

我正在使用以下代码:

from bs4 import BeautifulSoup
from selenium import webdriver
import time
import pandas as pd


urlpage = "https://bangladeshaccord.org/factories"
print(urlpage)

driver = webdriver.Chrome(executable_path=r"C:\Users\filippo.sebastio\chromedriver.exe")

driver.get(urlpage)
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);var lenOfPage=document.body.scrollHeight;return lenOfPage;")
time.sleep(30)

results = driver.find_elements_by_xpath("//*[@id='factories']/div[3]/div/div/div[2]/div[3]/div[1]/div[2]/div[1]/div[2]/span[2]")
print('Number of results', len(results))

结果我得到

https://bangladeshaccord.org/factories

Number of results 1

为什么我只得到一个结果?为什么我什至不能打印它?

谢谢!

原因是因为您提供的 xpath 只指向一个特定的元素,这就是为什么您只得到一个结果的原因。您应该使用 upper parrent div 获取所有结果框,然后获取它们的子 div 标签,最后是带有名称的 h2 标签。问题仍然是您要如何处理滚动负载?如果有另一种更好的方法,在 selenium 中进行自动滚动不是一个好主意。这是解决方案。检查网站,它向 API 发出 GET/POST 请求以获取所有数据,因此您甚至不必使用 UI 和 Selenium 来获取数据,您可以使用简单的GET/POST 个请求。这是第 1 页上使用默认过滤器搜索工厂的示例 URL:

https://accord2.fairfactories.org/api/v1/factories?status=active,inactive,no%20brand,pending%20closure&designation=completed,ontrack,behindschedule,capnotfinalised,notfinalized,initialcompleted&progress=0,1,2,3,4,5,6,7,8,9&language=en&limit=20&format=json&page=1

这里的所有参数都来自UI中的过滤器,所以如果你想改变搜索结果,你需要自定义它们。对下一页使用 page 参数(在 UI 中滚动加载更多内容)。

现在您有简单的 GET/POST 个请求和 JSON 个要解析的请求。

希望对您有所帮助。

要检索您需要为 visibility_of_all_elements_located() 引入 WebDriverWait 的结果数,您可以使用以下 :

  • 代码块:

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    options = webdriver.ChromeOptions()
    options.add_argument("start-maximized")
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option('useAutomationExtension', False)
    driver = webdriver.Chrome(options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
    driver.get("https://bangladeshaccord.org/factories")
    driver.execute_script("arguments[0].scrollIntoView(true);",WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//h3[contains(., 'Accord Factories ')]"))))
    myLength = len(WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//p[./span[text()='Remediation Status:']]//preceding::h2[1]"))))
    print(myLength)
    driver.quit()
    

如果您想获取所有公司条目,您可以逐步向下滚动到页面的按钮。由于 window.scrollTo 在这里不起作用,我只是 *document.getElementById('page-body').scrollTop = * 在这里。这样做将加载所有条目。

def scroll_to_bottom(driver):
    scroll_y = driver.execute_script("return document.getElementById('page-body').scrollTop")
    driver.execute_script("document.getElementById('page-body').scrollTop = {};".format(scroll_y+500))
    new_scroll_y = driver.execute_script("return document.getElementById('page-body').scrollTop")
    while (scroll_y < new_scroll_y):
        driver.execute_script("document.getElementById('page-body').scrollTop = {};".format(new_scroll_y+500))
        scroll_y = new_scroll_y
        new_scroll_y = driver.execute_script("return document.getElementById('page-body').scrollTop")
        time.sleep(2)

正如其他答案中所述,您必须使用不同的选择器。您的代码稍作更新后可能如下所示(向下滚动页面并最终打印出公司数量及其名称列表):

urlpage = "https://bangladeshaccord.org/factories"
print(urlpage)

webdriver.Chrome(executable_path=r"C:\Users\filippo.sebastio\chromedriver.exe")
driver.get(urlpage)
time.sleep(5)
scroll_to_bottom(driver)

results = driver.find_elements_by_class_name("sc-ldcLGC")

print('Number of results', len(results))
for res in results:
    company = res.find_element_by_css_selector('h2.sc-cAJUJo')
    print(company.get_attribute("textContent"))