ОБНОВЛЕНИЕ:
Из дальнейшего чтения журналов я понял, что немедленная попытка отправить другой запрос приводит к тому, что запрос вообще не отправляется.И 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