Селен в Python - один тайм-аут вызывает все последующие запросы на тайм-аут - PullRequest
0 голосов
/ 14 сентября 2018

Версия драйвера Chrome: 2.41 Версия Chrome: 69.0.3497.92

Вот мой код отправки нескольких запросов одному веб-драйверу с обработкой исключений:

from selenium import webdriver
from selenium.common.exceptions import *

options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')

driver = webdriver.Chrome('/usr/local/bin/chromedriver', chrome_options=options)
driver.set_page_load_timeout(30)

for link in links:
    try:
        driver.get(link)
    except TimeoutException as e:
        # do something
        continue
    except Exception as e:
        # do some other thing
        continue

Ожидаемое поведение было, если TimeoutExceptionскинул, я бы просто продолжал делать запросы на следующую ссылку и тд.Тем не менее, я получаю то, что при возникновении одного TimeoutException все остальные ссылки также генерируют TimeoutExceptions.

Вот соответствующий журнал из регистратора chrome.

[1536872569.507][SEVERE]: Timed out receiving message from renderer: 29.449
[1536872569.509][INFO]: Timed out. Stopping navigation...
[1536872569.509][DEBUG]: DEVTOOLS COMMAND Page.stopLoading (id=1243) {

}
[1536872569.509][DEBUG]: DEVTOOLS RESPONSE Page.stopLoading (id=1243) {

}
[1536872569.509][DEBUG]: DEVTOOLS COMMAND Runtime.evaluate (id=1244) {
   "expression": "1"
}
[1536872569.510][SEVERE]: Timed out receiving message from renderer: -0.002
[1536872569.513][INFO]: Done waiting for pending navigations. Status: timeout
[1536872569.513][INFO]: RESPONSE Navigate timeout
  (Session info: headless chrome=69.0.3497.92)
[1536872569.516][INFO]: COMMAND Navigate {
  "sessionId": "9caf0bad68147065f14c9c22632cd6d8",
   "url": "www.example.com"
}
[1536872569.516][DEBUG]: DEVTOOLS EVENT Page.frameStoppedLoading {
   "frameId": "620369B66F0605C0CE359F34F9D95E36"
}
[1536872569.516][DEBUG]: DEVTOOLS RESPONSE Runtime.evaluate (id=1244) {
   "result": {
      "description": "1",
      "type": "number",
      "value": 1
   }
}
[1536872569.516][INFO]: Waiting for pending navigations...
[1536872569.516][DEBUG]: DEVTOOLS COMMAND Runtime.evaluate (id=1245) {
   "expression": "1"
}
[1536872569.517][DEBUG]: DEVTOOLS RESPONSE Runtime.evaluate (id=1245) {
   "result": {
      "description": "1",
      "type": "number",
      "value": 1
   }
}
[1536872599.516][SEVERE]: Timed out receiving message from renderer: 30.000
[1536872599.518][INFO]: Timed out. Stopping navigation...
[1536872599.518][DEBUG]: DEVTOOLS COMMAND Page.stopLoading (id=1246) {

}
[1536872599.518][DEBUG]: DEVTOOLS RESPONSE Page.stopLoading (id=1246) {

}
[1536872599.518][DEBUG]: DEVTOOLS COMMAND Runtime.evaluate (id=1247) {
   "expression": "1"
}
[1536872599.518][SEVERE]: Timed out receiving message from renderer: -0.002
[1536872599.522][INFO]: Done waiting for pending navigations. Status: timeout
[1536872599.522][INFO]: RESPONSE Navigate timeout
  (Session info: headless chrome=69.0.3497.92)
[1536872599.524][INFO]: COMMAND Navigate {
   "sessionId": "9caf0bad68147065f14c9c22632cd6d8",
   "url": "www.example2.com"
}

Ниже приведены различия, которые я обнаружил при сравнении этого события с другими последующими запросами, которые были завершены без каких-либо исключений.

1) DEVTOOLS EVENT Page.frameStoppedLoading приходит сразу после отправки запроса на новый сайт «www.example.com».link.

2) после запроса на новый URL-адрес регистрируется ответ на DEVTOOLS COMMAND Runtime.evaluate (id=1244), отправленный по предыдущей ссылке.

Вопрос: isЕсть ли другой способ справиться с этим, кроме перезапуска драйвера с каждым TimeoutException?

Если бы кто-то мог также подробно рассказать о поведении, я бы очень признателен.Спасибо.

1 Ответ

0 голосов
/ 14 сентября 2018

ОБНОВЛЕНИЕ:

Из дальнейшего чтения журналов я понял, что немедленная попытка отправить другой запрос приводит к тому, что запрос вообще не отправляется.И 2 наблюдения, которые я сделал в своем первоначальном посте, происходят с успешными запросами, поэтому вы можете проигнорировать это.

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

Когда запускается драйвер chrome, сеанс браузера получает идентификатор (позже его называют frameId).

   [1536915601.693][DEBUG]: DevTools request: http://localhost:34899/json
   [1536915601.694][DEBUG]: DevTools response: [ {
      "description": "",
      "devtoolsFrontendUrl": "/devtools/inspector.html?ws=localhost:34899/devtools/page/A417CC5AE2C87A4D0FC64CF66B54ED72",
      "id": "A417CC5AE2C87A4D0FC64CF66B54ED72",
      "title": "data:,",
      "type": "page",
      "url": "data:,",
      "webSocketDebuggerUrl": "ws://localhost:34899/devtools/page/A417CC5AE2C87A4D0FC64CF66B54ED72"
   } ]


Сейчас case 1: normalзапрос после успешного ответа:

  [1536915607.033][INFO]: Done waiting for pending navigations. Status: ok
  [1536915607.033][INFO]: RESPONSE GetSource "\u003C!DOCTYPE html>\u003Chtml xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"ko\">\u003Chead>\u003Cmeta http-equiv=\"Content-Type\" content=\"text/h       tml; charset=utf-8\" />\n\u003Cmeta name=\"viewport\" content=\"width=device-width, in..."
  [1536915607.044][INFO]: COMMAND Navigate {
     "sessionId": "d11fb86ec1b49a141f99fe1ec4286a85",
     "url": "http://www.gelloy.com/product/detail.html?product_no=438&cate_no=30&display_group=1"
  } 
 # ------ skip for concisiveness ----- #
 [1536915607.044][INFO]: Done waiting for pending navigations. Status: ok
  [1536915607.044][DEBUG]: DEVTOOLS COMMAND Page.navigate (id=49) {
     "url": "http://www.gelloy.com/product/detail.html?product_no=438&cate_no=30&display_group=1"
  }
  [1536915609.244][DEBUG]: DEVTOOLS RESPONSE Page.navigate (id=49) {
     "frameId": "A417CC5AE2C87A4D0FC64CF66B54ED72",
     "loaderId": "0EB53CDA615428AA73A9DB67F5FF65E1"
  }

Здесь я вижу, что
- COMMAND Navigate - готовит следующий запрос
- COMMAND Page.navigate - отправляетrequest
- RESPONSE Page.navigate - возвращает с указанным в начале frameId

vs

case 2: запрос отправлен сразу после истечения времени ожиданиясработало:

  [1536872569.513][INFO]: Done waiting for pending navigations. Status: timeout
  [1536872569.513][INFO]: RESPONSE Navigate timeout
  (Session info: headless chrome=69.0.3497.92)
  [1536872569.516][INFO]: COMMAND Navigate {
  "sessionId": "9caf0bad68147065f14c9c22632cd6d8",
   "url": "www.example.com"
  }
  [1536872569.516][DEBUG]: DEVTOOLS EVENT Page.frameStoppedLoading {
   "frameId": "620369B66F0605C0CE359F34F9D95E36"
  }
  [1536872569.516][DEBUG]: DEVTOOLS RESPONSE Runtime.evaluate (id=1244) {
   "result": {
      "description": "1",
      "type": "number",
      "value": 1
   }
  }
  [1536872569.516][INFO]: Waiting for pending navigations...
  [1536872569.516][DEBUG]: DEVTOOLS COMMAND Runtime.evaluate (id=1245) {
   "expression": "1"
  }
  [1536872569.517][DEBUG]: DEVTOOLS RESPONSE Runtime.evaluate (id=1245) {
   "result": {
      "description": "1",
      "type": "number",
      "value": 1
   }
  }
[1536872599.516][SEVERE]: Timed out receiving message from renderer: 30.000

Однако по истечении времени ожидания я вижу COMMAND Navigate со следующим URL-адресом, но COMMAND Page.navigate никогда не происходит.Таким образом, когда 30 секунд истекло с момента создания COMMAND Navigate, драйвер определяет, была ли страница загружена или нет, исходя из результата самого последнего RESPONSE Page.navigate, что приводит к таймаутам после этого.


Решение

Я решил закрыть драйвер с помощью driver.quit() и снова открывать новый браузер каждый раз, когда возникает исключение тайм-аута.Установка time.sleep(1) перед продолжением цикла также, кажется, работает, но я не могу быть уверен, что 1 секунды достаточно.

Вот как выглядит мой обновленный код:

driver = webdriver.Chrome('/usr/local/bin/chromedriver', chrome_options=options)
driver.set_page_load_timeout(30)

for link in links:
    try:
        driver.get(link)
    except TimeoutException as e:
        # do something
        driver.quit()
        driver = webdriver.Chrome('/usr/local/bin/chromedriver', chrome_options=options)
        driver.set_page_load_timeout(30)           
        continue
    except Exception as e:
        # do some other thing
        continue
...