Сканирует данные с помощью Selenium, но выдает ошибки TimeoutException

Я пытался просмотреть отзывы на веб-сайтах. Для 1 сайта работает нормально. однако, когда я создаю цикл для обхода многих веб-сайтов, он вызывает ошибку

TimeoutException(сообщение, экран, трассировка стека) TimeoutException

Я попытался увеличить время ожидания с 30 до 50, но все равно не работает. вот мой код:

import requests
import pandas as pd
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from bs4 import BeautifulSoup
from datetime import datetime

start_time = datetime.now()

result = pd.DataFrame()
df = pd.read_excel(r'D:\check_bols.xlsx')
ids = df['ids'].values.tolist() 

link = "https://www.bol.com/nl/ajax/dataLayerEndpoint.html?product_id = "

for i in ids:
    
    link3 = link + str(i[-17:].replace("/",""))
    op = webdriver.ChromeOptions()
    op.add_argument('--ignore-certificate-errors')
    op.add_argument('--incognito')
    op.add_argument('--headless')
    driver = webdriver.Chrome(executable_path='D:/chromedriver.exe',options=op)
    driver.get(i)
    WebDriverWait(driver, 50).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-test='consent-modal-confirm-btn']>span"))).click()
    WebDriverWait(driver, 50).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a.review-load-more__button.js-review-load-more-button"))).click()

    soup = BeautifulSoup(driver.page_source, 'lxml')

    product_attributes = requests.get(link3).json()

    reviewtitle = [i.get_text() for i in soup.find_all("strong", class_ = "review__title") ]

    url = [i]*len(reviewtitle)

    productid = [product_attributes["dmp"]["productId"]]*len(reviewtitle)
  
    content= [i.get_text().strip()  for i in soup.find_all("div",attrs = {"class":"review__body"})]
    
    author = [i.get_text() for i in soup.find_all("li",attrs = {"data-test":"review-author-name"})]

    date  = [i.get_text() for i in soup.find_all("li",attrs = {"data-test":"review-author-date"})]

    output = pd.DataFrame(list(zip(url, productid,reviewtitle, author, content, date )))
    
    result.append(output)
    
    result.to_excel(r'D:\bols.xlsx', index=False)
    
end_time = datetime.now()
print('Duration: {}'.format(end_time - start_time))

Вот некоторые ссылки, которые я пытался просканировать:

ссылка1ссылка2

Какие ошибки в строке? - тайм-аут происходит, когда webdriverwait терпит неудачу, и это вместо nosuchelement - Подтвердите, что объект существует на ссылке, которая терпит неудачу. Например, ваше второе ожидание — это «a.review-load-more__button.js-review-load-more-button» — значит, это «кнопка «загрузить еще», но что, если для этого нет кнопки? Что делать, если отзывов нет или их больше не нужно загружать? (это истечет время поиска)

RichEdwards 11.12.2020 11:18

Ошибка линии - это второе ожидание, как вы упомянули. Как я могу исправить эту ошибку? Некоторые ссылки имеют более 5 отзывов, поэтому нужно нажать кнопку, некоторые нет. Что мне нужно изменить в коде, который работает в обеих ситуациях?

mht 11.12.2020 11:29

Отловите ошибку тайм-аута с помощью команды «Попробовать и исключить» -w3schools.com/python/python_try_except.asp — вам также потребуется импортировать эту ошибку в начале вашего скрипта.

RichEdwards 11.12.2020 11:34
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
250
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Как упоминалось в комментариях, время ожидания истекло, потому что вы ищете несуществующую кнопку.

Вам нужно поймать ошибку (ошибки) и пропустить эти ошибочные строки. Вы можете сделать это с попробовать и кроме.

Я собрал для вас пример. Он жестко закодирован для одного URL-адреса (поскольку у меня нет вашей таблицы данных), и это фиксированный цикл с целью продолжать ПЫТАТЬСЯ нажать кнопку «показать больше», даже после того, как она исчезла.

С этим решением будьте осторожны со временем синхронизации. КАЖДЫЙ РАЗ, когда вызывается WebDriverWait, он будет ждать всю продолжительность, если он не существует. Вам нужно будет выйти из цикла расширения, когда вы закончите (в первый раз, когда вы столкнетесь с ошибкой) и сохранить время синхронизации, иначе это будет медленный скрипт.

Сначала добавьте их в свой импорт:

from selenium.common.exceptions import TimeoutException
from selenium.common.exceptions import StaleElementReferenceException

Тогда это будет работать, а не ошибка:

#not a fixed url:
driver.get('https://www.bol.com/nl/p/Matras-180x200-7-zones-koudschuim-premium-plus-tijk-15-cm-hard/9200000130825457/')

#accept the cookie once
WebDriverWait(driver, 50).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-test='consent-modal-confirm-btn']>span"))).click()
   
for i in range(10):
    try:
        WebDriverWait(driver, 50).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a.review-load-more__button.js-review-load-more-button"))).click()
        print("I pressed load more")
    except (TimeoutException, StaleElementReferenceException):
        pass
        print("No more to load - but i didn't fail")

Вывод в консоль такой:

DevTools слушает ws://127.0.0.1:51223/devtools/браузер/4b1a0033-8294-428d-802a-d0d2127c4b6f

я нажал загрузить еще

я нажал загрузить еще

Больше нечего загружать, но я не ошибся

Больше нечего загружать, но я не ошибся

Больше нечего загружать, но я не ошибся

Больше нечего загружать, но я не ошибся (и так далее).

Вот как выглядит мой браузер — обратите внимание на размер полосы прокрутки для ссылки, которую я использовал — похоже, в ней есть все отзывы:

Я бы предложил использовать Infinite While loop и использовать блок try..except. Если элемент найден, он щелкнет по элементу, иначе оператор перейдет к блоку исключений и выйдет из цикла while.

driver.get("https://www.bol.com/nl/p/Matras-180x200-7-zones-koudschuim-premium-plus-tijk-15-cm-hard/9200000130825457/")
WebDriverWait(driver, 50).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-test='consent-modal-confirm-btn']>span"))).click()
while True:
    try:
        WebDriverWait(driver, 50).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a.review-load-more__button.js-review-load-more-button"))).click()
        print("Lode more button found and clicked ")
    except:
        print("No more load more button available on the page.Please exit...")
        break

Вывод вашей консоли будет отображаться, как показано ниже.

Lode more button found and clicked 
Lode more button found and clicked 
Lode more button found and clicked 
Lode more button found and clicked 
No more load more button available on the page.Please exit...

Другие вопросы по теме