В промежуточном программном обеспечении у меня возникла следующая проблема со скрапом:
Я делаю запрос на сайт с https, а также использую прокси. При определении промежуточного программного обеспечения и использовании в нем process_response
, response.headers
имеет только заголовки с веб-сайта. Есть ли способ получить заголовки из запроса CONNECT, который устанавливает туннель прокси? Используемый нами прокси-сервер добавляет некоторую информацию в качестве заголовков в этот ответ, мы хотим использовать ее в промежуточном программном обеспечении.
Я обнаружил, что в TunnelingTCP4ClientEndpoint.processProxyResponse
параметр rcvd_bytes
содержит всю необходимую мне информацию. Я не нашел способа получить rcvd_bytes
в своем промежуточном программном обеспечении.
Также я нашел похожую (аналогичную) проблему год назад, которая не решена: Не получает заголовки Scrapy ProxyMesh
Вот пример с прокси-сайта:
Для HTTPS IP находится в заголовке ответа CONNECT. Пример x-hola-ip для IP-адреса прокси-сервера 5.6.7.8:
.
Request
CONNECT example.com:80 HTTP/1.1
Host: example.com:80
Accept: */*
Response:
HTTP/1.1 200 OK
Content-Type: text/html
x-hola-ip: 5.6.7.8
Я хочу получить x-hola-ip в этом примере.
При использовании curl типа curl --proxy mysuperproxy https://stackoverflow.com
я получаю также правильные данные в ответе CONNECT.
Если это невозможно, моё возможное решение состоит в том, чтобы как-то до сих пор исправлять класс, или, возможно, вы знаете лучшее решение для этого в python.
Заранее спасибо за помощь.
Примечание: я также разместил этот вопрос на github проблем scrapy, я обновлю оба сайта, если найду какое-либо решение:)
Рабочий раствор с помощью Матфея:
from scrapy.core.downloader.handlers.http11 import (
HTTP11DownloadHandler, ScrapyAgent, TunnelingTCP4ClientEndpoint, TunnelError, TunnelingAgent
)
from scrapy import twisted_version
class MyHTTPDownloader(HTTP11DownloadHandler):
i = ''
def download_request(self, request, spider):
# we're just overriding here to monkey patch the attribute
agent = ScrapyAgent(contextFactory=self._contextFactory, pool=self._pool,
maxsize=getattr(spider, 'download_maxsize', self._default_maxsize),
warnsize=getattr(spider, 'download_warnsize', self._default_warnsize),
fail_on_dataloss=self._fail_on_dataloss)
agent._TunnelingAgent = MyTunnelingAgent
return agent.download_request(request)
class MyTunnelingAgent(TunnelingAgent):
if twisted_version >= (15, 0, 0):
def _getEndpoint(self, uri):
return MyTunnelingTCP4ClientEndpoint(
self._reactor, uri.host, uri.port, self._proxyConf,
self._contextFactory, self._endpointFactory._connectTimeout,
self._endpointFactory._bindAddress)
else:
def _getEndpoint(self, scheme, host, port):
return MyTunnelingTCP4ClientEndpoint(
self._reactor, host, port, self._proxyConf,
self._contextFactory, self._connectTimeout,
self._bindAddress)
class MyTunnelingTCP4ClientEndpoint(TunnelingTCP4ClientEndpoint):
def processProxyResponse(self, rcvd_bytes):
# log('hier rcvd_bytes')
MyHTTPDownloader.i = rcvd_bytes
return super(MyTunnelingTCP4ClientEndpoint, self).processProxyResponse(rcvd_bytes)
А в ваших настройках:
DOWNLOAD_HANDLERS = {
'http': 'crawler.MyHTTPDownloader.MyHTTPDownloader',
'https': 'crawler.MyHTTPDownloader.MyHTTPDownloader',
}