La secuencia de comandos de repente deja de rastrear sin error o excepción

No estoy seguro de por qué, pero mi script siempre deja de rastrear una vez que llega a la página 9 . No hay errores, excepciones o advertencias, así que estoy un poco perdido.

alguien me puede ayudar?

PS ¡ Aquí está el script completo en caso de que alguien quiera probarlo por sí mismo!

def initiate_crawl(): def refresh_page(url): ff = create_webdriver_instance() ff.get(url) ff.find_element(By.XPATH, '//*[@id="FilterItemView_sortOrder_dropdown"]/div/span[2]/span/span/span/span').click() ff.find_element(By.XPATH, '//a[contains(text(), "Discount - High to Low")]').click() items = WebDriverWait(ff, 15).until( EC.visibility_of_all_elements_located((By.XPATH, '//div[contains(@id, "100_dealView_")]')) ) print(len(items)) for count, item in enumerate(items): slashed_price = item.find_elements(By.XPATH, './/span[contains(@class, "a-text-strike")]') active_deals = item.find_elements(By.XPATH, './/*[contains(text(), "Add to Cart")]') if len(slashed_price) > 0 and len(active_deals) > 0: product_title = item.find_element(By.ID, 'dealTitle').text if product_title not in already_scraped_product_titles: already_scraped_product_titles.append(product_title) url = ff.current_url ff.quit() refresh_page(url) break if count+1 is len(items): try: next_button = WebDriverWait(ff, 15).until( EC.text_to_be_present_in_element((By.PARTIAL_LINK_TEXT, 'Next→'), 'Next→') ) ff.find_element(By.PARTIAL_LINK_TEXT, 'Next→').click() url = ff.current_url ff.quit() refresh_page(url) except Exception as error: print(error) ff.quit() refresh_page('https://www.amazon.ca/gp/goldbox/ref=gbps_ftr_s-3_4bc8_dct_10-?gb_f_c2xvdC0z=sortOrder:BY_SCORE,discountRanges:10-25%252C25-50%252C50-70%252C70-&pf_rd_p=f5836aee-0969-4c39-9720-4f0cacf64bc8&pf_rd_s=slot-3&pf_rd_t=701&pf_rd_i=gb_main&pf_rd_m=A3DWYIK6Y9EEQB&pf_rd_r=CQ7KBNXT36G95190QJB1&ie=UTF8') initiate_crawl() 

Imprimir la longitud de los items invoca algún comportamiento extraño también. En lugar de devolver siempre 32, lo que correspondería al número de elementos en cada página, imprime 32 para la primera página, 64 para la segunda, 96 para la tercera, etc., etc. //div[contains(@id, "100_dealView_")]/div[contains(@class, "dealContainer")] esto utilizando //div[contains(@id, "100_dealView_")]/div[contains(@class, "dealContainer")] lugar de //div[contains(@id, "100_dealView_")] como XPath para la variable de items . Espero que esta sea la razón por la que se encuentra con problemas en la página 9. Estoy realizando pruebas en este momento. Actualización: ahora está raspando la página 10 y más allá, por lo que el problema se resuelve.

Según su 10ª revisión de esta pregunta, el mensaje de error …

 HTTPConnectionPool(host='127.0.0.1', port=58992): Max retries exceeded with url: /session/e8beed9b-4faa-4e91-a659-56761cb604d7/element (Caused by NewConnectionError(': Failed to establish a new connection: [WinError 10061] No connection could be made because the target machine actively refused it')) 

… implica que el método get() falló al generar el error HTTPConnectionPool con un mensaje Se rebasaron los rebashs máximos .

Un par de cosas:

  • De acuerdo con la discusión , las excepciones de rebashs máximos son confusas, ya que el rastreo es algo engañoso. Las solicitudes envuelven la excepción para la conveniencia de los usuarios. La excepción original es parte del mensaje mostrado.
  • Las solicitudes nunca se reintentan (establece los retries=0 para el HTTPConnectionPool de HTTPConnectionPool ), por lo que el error hubiera sido mucho más canónico sin las palabras clave MaxRetryError y HTTPConnectionPool . Así que un Traceback ideal hubiera sido:

     NewConnectionError(: [Errno 10061] No connection could be made because the target machine actively refused it) 
  • Encontrará una explicación detallada en MaxRetryError: HTTPConnectionPool: Max rebashs excedidos (Causado por ProtocolError (‘Conexión cancelada.’, Error (111, ‘Conexión rechazada’)))

Solución

Según las Notas de la versión de Selenium 3.14.1 :

 * Fix ability to set timeout for urllib3 (#6286) 

La combinación es: ¡ reparar urllib3 no puede establecer el tiempo de espera!

Conclusión

Una vez que actualice a Selenium 3.14.1 , podrá establecer el tiempo de espera y ver Tracebacks canónicos, y podrá tomar las medidas necesarias.

Referencias

Un par de referencias relevantes:

  • Añadiendo max_retries como argumento
  • Se eliminó la farsa y urllib3 agrupados.
  • Bibliotecas de terceros comprometidas textualmente.

Este caso de uso

He tomado su guión completo de codepen.io – A PEN BY Anthony . Tuve que hacer algunos ajustes a tu código existente de la siguiente manera:

  • Como has utilizado:

     ua_string = random.choice(ua_strings) 

    Tienes que importar obligatoriamente al random como:

     import random 
  • Has creado la variable next_button pero no la has usado. He golpeado las siguientes cuatro líneas:

     next_button = WebDriverWait(ff, 15).until( EC.text_to_be_present_in_element((By.PARTIAL_LINK_TEXT, 'Next→'), 'Next→') ) ff.find_element(By.PARTIAL_LINK_TEXT, 'Next→').click() 

    Como:

     WebDriverWait(ff, 15).until(EC.text_to_be_present_in_element((By.PARTIAL_LINK_TEXT, 'Next→'), 'Next→')) ff.find_element(By.PARTIAL_LINK_TEXT, 'Next→').click() 
  • Su bloque de código modificado será:

     # -*- coding: utf-8 -*- from selenium import webdriver from selenium.webdriver.firefox.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait import time import random """ Set Global Variables """ ua_strings = ['Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'] already_scraped_product_titles = [] """ Create Instances of WebDriver """ def create_webdriver_instance(): ua_string = random.choice(ua_strings) profile = webdriver.FirefoxProfile() profile.set_preference('general.useragent.override', ua_string) options = Options() options.add_argument('--headless') return webdriver.Firefox(profile) """ Construct List of UA Strings """ def fetch_ua_strings(): ff = create_webdriver_instance() ff.get('https://techblog.willshouse.com/2012/01/03/most-common-user-agents/') ua_strings_ff_eles = ff.find_elements_by_xpath('//td[@class="useragent"]') for ua_string in ua_strings_ff_eles: if 'mobile' not in ua_string.text and 'Trident' not in ua_string.text: ua_strings.append(ua_string.text) ff.quit() """ Log in to Amazon to Use SiteStripe in order to Generate Affiliate Links """ def log_in(ff): ff.find_element(By.XPATH, '//a[@id="nav-link-yourAccount"] | //a[@id="nav-link-accountList"]').click() ff.find_element(By.ID, 'ap_email').send_keys('anthony_falez@hotmail.com') ff.find_element(By.ID, 'continue').click() ff.find_element(By.ID, 'ap_password').send_keys('lo0kyLoOkYig0t4h') ff.find_element(By.NAME, 'rememberMe').click() ff.find_element(By.ID, 'signInSubmit').click() """ Build Lists of Product Page URLs """ def initiate_crawl(): def refresh_page(url): ff = create_webdriver_instance() ff.get(url) ff.find_element(By.XPATH, '//*[@id="FilterItemView_sortOrder_dropdown"]/div/span[2]/span/span/span/span').click() ff.find_element(By.XPATH, '//a[contains(text(), "Discount - High to Low")]').click() items = WebDriverWait(ff, 15).until( EC.visibility_of_all_elements_located((By.XPATH, '//div[contains(@id, "100_dealView_")]')) ) for count, item in enumerate(items): slashed_price = item.find_elements(By.XPATH, './/span[contains(@class, "a-text-strike")]') active_deals = item.find_elements(By.XPATH, './/*[contains(text(), "Add to Cart")]') # For Groups of Items on Sale # active_deals = //*[contains(text(), "Add to Cart") or contains(text(), "View Deal")] if len(slashed_price) > 0 and len(active_deals) > 0: product_title = item.find_element(By.ID, 'dealTitle').text if product_title not in already_scraped_product_titles: already_scraped_product_titles.append(product_title) url = ff.current_url # Scrape Details of Each Deal #extract(ff, item.find_element(By.ID, 'dealImage').get_attribute('href')) print(product_title[:10]) ff.quit() refresh_page(url) break if count+1 is len(items): try: print('') print('new page') WebDriverWait(ff, 15).until(EC.text_to_be_present_in_element((By.PARTIAL_LINK_TEXT, 'Next→'), 'Next→')) ff.find_element(By.PARTIAL_LINK_TEXT, 'Next→').click() time.sleep(10) url = ff.current_url print(url) print('') ff.quit() refresh_page(url) except Exception as error: """ ff.find_element(By.XPATH, '//*[@id="pagination-both-004143081429407891"]/ul/li[9]/a').click() url = ff.current_url ff.quit() refresh_page(url) """ print('cannot find ff.find_element(By.PARTIAL_LINK_TEXT, "Next?")') print('Because of... {}'.format(error)) ff.quit() refresh_page('https://www.amazon.ca/gp/goldbox/ref=gbps_ftr_s-3_4bc8_dct_10-?gb_f_c2xvdC0z=sortOrder:BY_SCORE,discountRanges:10-25%252C25-50%252C50-70%252C70-&pf_rd_p=f5836aee-0969-4c39-9720-4f0cacf64bc8&pf_rd_s=slot-3&pf_rd_t=701&pf_rd_i=gb_main&pf_rd_m=A3DWYIK6Y9EEQB&pf_rd_r=CQ7KBNXT36G95190QJB1&ie=UTF8') #def extract_info(ff, url): fetch_ua_strings() initiate_crawl() 
  • Salida de consola: Con Selenium v3.14.0 y Firefox Quantum v62.0.3 , puedo extraer la siguiente salida en la consola:

     J.Rosée Si B.Catcher Bluetooth4 FRAM G4164 Major Crim 20% off Oh True Blood Prime-Line Marathon 3 True Blood B.Catcher 4 Film Fav True Blood Texture Pa Westinghou True Blood ThermoPro ... ... ... 

Nota : Pude haber optimizado su código y realizar las mismas operaciones de desguace web que inicializaron el cliente del navegador Firefox solo una vez y atravesar varios productos y sus detalles. Pero para preservar su lógica e innovación , he sugerido los cambios mínimos necesarios para lograrlo.

Ajusté ligeramente el código y parece funcionar. Cambios:

import random statement import random porque se usa y no se ejecutaría sin ella.

Dentro de product_title loop se eliminan estas líneas:

ff.quit() , refresh_page(url) y break

La statement ff.quit() causaría un error fatal (conexión) que causaba que el script se rompiera.

También is cambia a == if count + 1 == len(item):

 # -*- coding: utf-8 -*- from selenium import webdriver from selenium.webdriver import Firefox from selenium.webdriver.firefox.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait import time import random """ Set Global Variables """ ua_strings = ['Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'] already_scraped_product_titles = [] """ Create Instances of WebDriver """ def create_webdriver_instance(): ua_string = random.choice(ua_strings) profile = webdriver.FirefoxProfile() profile.set_preference('general.useragent.override', ua_string) options = Options() options.add_argument('--headless') return webdriver.Firefox(profile) """ Construct List of UA Strings """ def fetch_ua_strings(): ff = create_webdriver_instance() ff.get('https://techblog.willshouse.com/2012/01/03/most-common-user-agents/') ua_strings_ff_eles = ff.find_elements_by_xpath('//td[@class="useragent"]') for ua_string in ua_strings_ff_eles: if 'mobile' not in ua_string.text and 'Trident' not in ua_string.text: ua_strings.append(ua_string.text) ff.quit() """ Build Lists of Product Page URLs """ def initiate_crawl(): def refresh_page(url): ff = create_webdriver_instance() ff.get(url) ff.find_element(By.XPATH, '//*[@id="FilterItemView_sortOrder_dropdown"]/div/span[2]/span/span/span/span').click() ff.find_element(By.XPATH, '//a[contains(text(), "Discount - High to Low")]').click() items = WebDriverWait(ff, 15).until( EC.visibility_of_all_elements_located((By.XPATH, '//div[contains(@id, "100_dealView_")]')) ) print(items) for count, item in enumerate(items): slashed_price = item.find_elements(By.XPATH, './/span[contains(@class, "a-text-strike")]') active_deals = item.find_elements(By.XPATH, './/*[contains(text(), "Add to Cart")]') # For Groups of Items on Sale # active_deals = //*[contains(text(), "Add to Cart") or contains(text(), "View Deal")] if len(slashed_price) > 0 and len(active_deals) > 0: product_title = item.find_element(By.ID, 'dealTitle').text if product_title not in already_scraped_product_titles: already_scraped_product_titles.append(product_title) url = ff.current_url # Scrape Details of Each Deal #extract(ff, item.find_element(By.ID, 'dealImage').get_attribute('href')) print(product_title[:10]) # This ff.quit()-line breaks connection which breaks things.: #ff.quit() # And why #refresh_page(url) #break # 'is' tests for object equality; == tests for value equality: if count+1 == len(items): try: print('') print('new page') next_button = WebDriverWait(ff, 15).until( EC.text_to_be_present_in_element((By.PARTIAL_LINK_TEXT, 'Next→'), 'Next→') ) ff.find_element(By.PARTIAL_LINK_TEXT, 'Next→').click() time.sleep(3) url = ff.current_url print(url) print('') ff.quit() refresh_page(url) except Exception as error: """ ff.find_element(By.XPATH, '//*[@id="pagination-both-004143081429407891"]/ul/li[9]/a').click() url = ff.current_url ff.quit() refresh_page(url) """ print('cannot find ff.find_element(By.PARTIAL_LINK_TEXT, "Next→")') print('Because of... {}'.format(error)) ff.quit() refresh_page('https://www.amazon.ca/gp/goldbox/ref=gbps_ftr_s-3_4bc8_dct_10-?gb_f_c2xvdC0z=sortOrder:BY_SCORE,discountRanges:10-25%252C25-50%252C50-70%252C70-&pf_rd_p=f5836aee-0969-4c39-9720-4f0cacf64bc8&pf_rd_s=slot-3&pf_rd_t=701&pf_rd_i=gb_main&pf_rd_m=A3DWYIK6Y9EEQB&pf_rd_r=CQ7KBNXT36G95190QJB1&ie=UTF8') #def extract_info(ff, url): fetch_ua_strings() initiate_crawl()