Скрипт внезапно прекращает сканирование без ошибок или исключений

Я не уверен, почему, но мой скрипт всегда прекращает сканирование, как только достигает стр. 9. Здесь нет ошибок, исключений или предупреждений, поэтому я немного растерялся.

Кто-нибудь может мне помочь?

P.S. Вот полный сценарий на тот случай, если кто-то захочет проверить его на себе!

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

Печать длины items тоже вызывает странное поведение. Вместо того, чтобы всегда возвращать 32, что соответствовало бы количеству элементов на каждой странице, он печатает 32 для первой страницы, 64 для второй, 96 для третьей и т. Д. И т. Д. Я исправил это, используя //div[contains(@id, "100_dealView_")]/div[contains(@class, "dealContainer")] вместо //div[contains(@id, "100_dealView_")] в качестве XPath для переменной items. Я надеюсь, что это причина, по которой возникают проблемы на странице 9. Я провожу тесты прямо сейчас. Обновление. Сейчас выполняется парсинг страницы 10 и более поздних, поэтому проблема решена.


person oldboy    schedule 07.10.2018    source источник
comment
Вы следили за процессом сканирования? Есть ли еще такие кнопки, как "Еще" на 9-й странице?   -  person jihan1008    schedule 07.10.2018
comment
@ jihan1008 все контролируется. ive проверил xpath, все, вроде ничего не сломано   -  person oldboy    schedule 07.10.2018
comment
Можете ли вы проверить в разных версиях браузера   -  person NarendraR    schedule 07.10.2018
comment
@NarendraR, я не совсем уверен, как это сделать? Как я могу это сделать?   -  person oldboy    schedule 07.10.2018
comment
Мне не удалось запустить ваш скрипт, но похоже, что в какой-то момент вы получаете элементы длины 0, и поэтому цикл перечисления не происходит. Попробуйте напечатать длину элементов до цикла и посмотрите, что произойдет до завершения кода.   -  person Andrew McDowell    schedule 07.10.2018
comment
@AndrewMcDowell хорошая идея! Я нахожусь в точке, где, я считаю, это должно быть где-то еще в сценарии. В настоящее время я установил кучу time.sleep(n) и провожу тест с этим. после этого напечатаю длину! спасибо за вклад ‹3   -  person oldboy    schedule 07.10.2018
comment
@AndrewMcDowell ты думаешь, что он выдаст ошибку, если items не сможет ничего найти. я имею в виду, это должно или выдать ошибку. Тем не менее, стоит изучить этот пункт   -  person oldboy    schedule 07.10.2018
comment
@AndrewMcDowell, поэтому я заметил кое-что очень странное: вместо len(items), возвращающего количество элементов на каждой странице, он возвращает 32 для первой страницы, затем 64 для второй страницы (33-64), 96 для третьей ( 65-96) и так далее ... как такое может происходить ?? с   -  person oldboy    schedule 08.10.2018
comment
Это странно, и я не ожидал такого поведения, но это может быть побочным эффектом того, как закодирован сайт. Это могло быть причиной проблемы, но если это так, я предполагаю, что проблема может возникнуть уже на странице 2, поэтому, боюсь, у меня нет идей. Удачи!   -  person Andrew McDowell    schedule 08.10.2018
comment
@AndrewMcDowell, это должно иметь какое-то отношение к сайту, так как я quit экземпляр webdriver, а затем создаю другой экземпляр заново ... человек протестировал гораздо более длинные скрипты на Amazon, и похоже, что они сделали почти все, что в их силах, чтобы попробовать и не допускать соскабливания / дозирования материала. несчастный   -  person oldboy    schedule 08.10.2018
comment
@AndrewMcDowell, поэтому я немного изменил свой скрипт и продублировал оператор if count+1... на том же уровне, что и оператор if product_title not in, и получил следующую ошибку: HTTPConnectionPool(host='127.0.0.1', port=58992): Max retries exceeded with url: /session/e8beed9b-4faa-4e91-a659-56761cb604d7/element (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x0000022D31378A58>: Failed to establish a new connection: [WinError 10061] No connection could be made because the target machine actively refused it')), что странно, поскольку я никогда не получал [продолжение]   -  person oldboy    schedule 08.10.2018
comment
@AndrewMcDowell ... ошибка, подобная этой раньше. obvs это означает, что Amazon активно отказывается от моего подключения к этой странице. не уверен, почему только дополнительный оператор if вызовет это   -  person oldboy    schedule 08.10.2018


Ответы (2)


В соответствии с вашей 10 -ой версией этого вопроса сообщение об ошибке ...

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

... означает, что метод get() не смог вызвать ошибку HTTPConnectionPool с сообщением Превышено максимальное количество попыток.

Пара вещей:

Решение

Согласно примечаниям к выпуску Selenium 3.14.1:

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

Слияние: восстановление urllib3 не может установить тайм-аут!

Заключение

После обновления до Selenium 3.14.1 вы сможете установить тайм-аут и увидеть канонические трассировки и предпринять необходимые действия.

использованная литература

Несколько соответствующих ссылок:


Этот вариант использования

Я взял ваш полный сценарий из codepen.io - ПЕНА Энтони. Мне пришлось внести несколько изменений в существующий код следующим образом:

  • Как вы использовали:

      ua_string = random.choice(ua_strings)
    

Вы должны обязательно импортировать random как:

    import random
  • Вы создали переменную next_button, но не использовали ее. Я собрал следующие четыре строчки:

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

    As:

      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()              
    
  • Ваш измененный блок кода будет:

      # -*- 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('[email protected]')
          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()
    
  • Вывод в консоль: с помощью Selenium v3.14.0 и Firefox Quantum v62.0.3 я могу извлечь в консоль следующий вывод:

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

Примечание. Я мог бы оптимизировать ваш код и выполнить те же операции очистки веб-страниц, инициализируя только клиент браузера Firefox < strong> once и пройдитесь по различным продуктам и их деталям. Но чтобы сохранить вашу логику и новаторство, я предложил минимальные изменения, необходимые для того, чтобы вы могли пройти через это.

person DebanjanB    schedule 10.10.2018
comment
Эта HTTPConnectionPool ошибка в моем вопросе - выброс. Скрипт работает отлично, пока не останавливается на странице 9 без ошибок или исключений. Единственная причина, по которой я установил, но не использовал next_button, заключается в том, что я пытался устранить это, думал, что это могло иметь какое-то отношение к этому, и никогда не сбрасывал его. Здесь возникает вопрос / проблема: почему он прекращает сканирование / считывание после завершения страницы 9 ?? - person oldboy; 10.10.2018
comment
о, может быть, поэтому я никогда не сбрасывал его. WebDriverWait(ff, 15).until(EC.text_to_be_present_in_element((By.PARTIAL_LINK_TEXT, 'Next→'), 'Next→')).click() возвращает bool object, на который нельзя щелкнуть. у вас есть ошибка в вашем коде - person oldboy; 10.10.2018
comment
@Anthony По вашему мнению, я внес небольшие изменения в свое решение. Я мог бы оптимизировать ваш код и выполнить ту же самую очистку веб-страниц, открыв клиент браузера Firefox только один раз и пройдя через различные продукты. Но чтобы сохранить вашу логику и новаторство, я предложил минимальные изменения, необходимые для вас. Не могли бы вы попробовать обновленное решение и сообщить мне статус? - person DebanjanB; 11.10.2018
comment
Я действительно исправил проблему самостоятельно несколько дней назад. Я обновил свой вопрос и просто обновил его снова для ясности. да, есть конкретная причина, по которой я не прохожу по веб-сайту с помощью одного экземпляра, а вместо этого создаю несколько экземпляров. хотя теперь, когда я думаю об этом, создание новых экземпляров может даже не потребоваться с ff.back() функциональностью, но это все же, безусловно, намного проще. Я прочту твой ответ, когда у меня будет свободное время! спасибо за попытку решить мою проблему ‹3 - person oldboy; 12.10.2018

Я немного поправил код и вроде работает. Изменения:

import random, потому что он используется и не будет работать без него.

Внутри цикла product_title эти строки удалены:

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

Оператор ff.quit() вызовет фатальную ошибку (соединение) и вызовет сбой сценария.

Также is изменился на == для 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()
person Wieger    schedule 10.10.2018