- PVSM.RU - https://www.pvsm.ru -
Добрый день, дорогие друзья.
Недавно, сидя на диване, я задумался о том, что хочется мне сделать своего паука, который что-то бы смог качать с веб сайтов. Но качать он должен был бы не простой загрузкой, а как настоящий милый добрый браузер (т.е. JavaScript чтобы исполнялся).
В моей голове всплыли такие интересные штуки, как Selenium, PhantomJS, Splash и всякое подобное. Все эти штуки были мне немного втягость. Вот какие причины я выявил:
Собственно, к делу. Недавно вышел Headless Chrome [1]. Это означает, что теперь мы аж использовать хром, как кравлер (но это не точно). Однако, я не нашел нормальных утилит для использования его в качестве кравлера. Нашел только chrome-remote-interface [2] из списка сторонних клиентов [3] (остальные были крайне скучными и совсем непонятными на первый взгляд).
Пробежавшись по документации и готовому проекту, и убедившись что никто толком не реализовал клиент под Python, я решил сделать свой клиент.
Протокол у Chrome Remote Debug достаточно простой. Для начала нам надо запустить Chrome вот с такими параметрами:
chrome --incognito --remote-debugging-port=9222 --headless
Теперь у нас есть API, доступное, по адресу http://127.0.0.1:9222/json/ [4], в котором я обнаружил такие методы как list [5], new [6], activate [7], version [8], которые используются для управления вкладками.
Также, если мы просто перейдем на http://127.0.0.1:9222/ [9], то сможем перейти на прекрасный веб отладчик, который полностью имитирует стандартный. В нем очень удобно отслеживать как работают апишные методы хрома (окно отладки справа эмулируется внутри окна, а окно браузера — отрисовано на канвасе).
Собственно, перейдя на вкладку list [5], мы можем узнать, адрес вебсокета, с помощью которого мы сможем общаться с вкладкой.
Дальше мы подсоединяемся через вебсокет к желаемой вкладке, и общаемся с нею. Мы можем:
Спустя дни мучительного написания функционала для себя у меня получилась вот такая библиотека [10].
Что в ней есть:
Вот так выглядит прога, которая подгружает страничку и выдает длину каждого ответа на запрос:
import asyncio
import chrome_remote_interface
if __name__ == '__main__':
class callbacks:
async def start(tabs):
tab = await tabs.add()
await tab.Page.enable()
await tab.Network.enable()
await tab.Page.navigate(url='http://github.com')
async def network__response_received(tabs, tab, requestId, **kwargs):
try:
body = tabs.helpers.unpack_response_body(await tab.Network.get_response_body(requestId=requestId))
print('body length:', len(body))
except tabs.FailReponse as e:
print('fail:', e)
async def network__loading_finished(tabs, tab, **kwargs):
print('finish')
tabs.terminate()
async def any(tabs, tab, callback_name, parameters):
pass
# print('Unknown event fired', callback_name)
asyncio.get_event_loop().run_until_complete(chrome_remote_interface.Tabs.run('localhost', 9222, callbacks))
Тут мы используем систему колбеков. Самые интересные: start и any:
Мне мой код показался достаточно элегантным, и я буду его использовать дальше, хоть протокол немного сыроват. Если кто-то хочет обсудить, то пишите сюда, в Github [12] или мне на почту [13].
Однако, было одно но, из за которого я все таки плачу. С помощью remote API нельзя производить перехват и модификацию запросов и ответов. Насколько я понял — это возможно через mojo [14], который позволяет использовать хром в качестве библиотеки.
Однако, я подумал, что компиляция нестабильного хрома и отсутствие Python прослойки для меня будет большим горем (сейчас есть C++ и JavaScript в процессе разработки).
Надеюсь, статья была полезной. Спасибо.
Автор: mitinsvyat
Источник [15]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/255391
Ссылки в тексте:
[1] Headless Chrome: https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md
[2] chrome-remote-interface: https://github.com/cyrus-and/chrome-remote-interface
[3] списка сторонних клиентов: https://developer.chrome.com/devtools/docs/debugging-clients#chrome-remote-interface
[4] http://127.0.0.1:9222/json/: http://127.0.0.1:9222/json/
[5] list: http://127.0.0.1:9222/json/list/
[6] new: http://127.0.0.1:9222/json/new/
[7] activate: http://127.0.0.1:9222/json/activate/
[8] version: http://127.0.0.1:9222/json/version/
[9] http://127.0.0.1:9222/: http://127.0.0.1:9222/
[10] библиотека: https://github.com/wasiher/chrome_remote_interface_python
[11] Network.responseReceived: https://chromedevtools.github.io/devtools-protocol/tot/Network/#event-responseReceived
[12] Github: https://github.com/wasiher
[13] почту: mailto:watashiwaher@gmail.com
[14] mojo: https://chromium.googlesource.com/chromium/src/+/master/mojo/README.md
[15] Источник: https://habrahabr.ru/post/328800/?utm_source=habrahabr&utm_medium=rss&utm_campaign=sandbox
Нажмите здесь для печати.