Динамическая очистка с помощью Selenium и Python не дает результатов - PullRequest
0 голосов
/ 31 октября 2019

Я пытаюсь очистить следующую страницу, используя селен, чтобы получить названия всех фабрик:

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

Количество результатов 1

Почему я получаю только один результат? и почему я даже не могу его напечатать?

Спасибо!

Ответы [ 3 ]

1 голос
/ 31 октября 2019

Причина в том, что указанный вами xpath указывает только на определенный элемент, и поэтому вы получаете только один результат. Вы должны использовать верхний parrent div, чтобы получить все поля результатов, а затем получить их дочерние теги div и, наконец, тег h2 с именем. Остается проблема, что ты собираешься делать с нагрузкой на свиток? Делать автопрокрутку в селене не очень хорошая идея, если есть другой лучший подход. Вот решение. Проверяя веб-сайт, он отправляет запросы GET / POST к API для получения всех данных, поэтому вам даже не нужно использовать пользовательский интерфейс и Selenium для получения данных, вы можете использовать простые запросы GET / POST. Вот пример URL-адреса для фабрик, выполняющих поиск с фильтрами по умолчанию на странице 1:

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

Все параметры здесь взяты из фильтров в пользовательском интерфейсе, поэтому вам нужно настроить их, если вы хотитеизменить результат поиска. Используйте параметр page для следующих страниц (загружая больше при прокрутке в пользовательском интерфейсе).

Теперь у вас есть простые запросы GET / POST и JSON to pars.

Надеюсь, что это поможет.

0 голосов
/ 31 октября 2019

Если вы хотите получить все записи компании, вы можете постепенно прокрутить вниз до кнопки страницы. Так как 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"))
0 голосов
/ 31 октября 2019

Для получения количества результатов, которое вам нужно вызвать WebDriverWait для visibility_of_all_elements_located(), и вы можете использовать следующие Стратегии локатора :

  • Кодовый блок:

    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()
    
...