2015-05-12 40 views
9

Podczas odskrobywania przy użyciu scrapy od czasu do czasu pojawia się w moich dziennikach jeden błąd. To nie wydaje się być w moim kodzie, i wygląda na to, że coś wewnątrz skręcony \ openssl. Wszelkie pomysły, które spowodowały to i jak się go pozbyć?Obiekt 'NoneType' nie ma atrybutu '_app_data' w scrapy twisted openssl

StackTrace tutaj:

[Launcher,27487/stderr] Error during info_callback 
    Traceback (most recent call last): 
     File "/opt/webapps/link_crawler/lib/python2.7/site-packages/twisted/protocols/tls.py", line 415, in dataReceived 
     self._write(bytes) 
     File "/opt/webapps/link_crawler/lib/python2.7/site-packages/twisted/protocols/tls.py", line 554, in _write 
     sent = self._tlsConnection.send(toSend) 
     File "/opt/webapps/link_crawler/lib/python2.7/site-packages/OpenSSL/SSL.py", line 1270, in send 
     result = _lib.SSL_write(self._ssl, buf, len(buf)) 
     File "/opt/webapps/link_crawler/lib/python2.7/site-packages/OpenSSL/SSL.py", line 926, in wrapper 
     callback(Connection._reverse_mapping[ssl], where, return_code) 
    --- <exception caught here> --- 
     File "/opt/webapps/link_crawler/lib/python2.7/site-packages/twisted/internet/_sslverify.py", line 1055, in infoCallback 
     return wrapped(connection, where, ret) 
     File "/opt/webapps/link_crawler/lib/python2.7/site-packages/twisted/internet/_sslverify.py", line 1157, in _identityVerifyingInfoCallback 
     transport = connection.get_app_data() 
     File "/opt/webapps/link_crawler/lib/python2.7/site-packages/OpenSSL/SSL.py", line 1589, in get_app_data 
     return self._app_data 
     File "/opt/webapps/link_crawler/lib/python2.7/site-packages/OpenSSL/SSL.py", line 1148, in __getattr__ 
     return getattr(self._socket, name) 
    exceptions.AttributeError: 'NoneType' object has no attribute '_app_data' 
+0

Nie umieszczaj części pytania na innej stronie. Umieść ślad stosu w pytaniu w linii. –

+0

Przydałby się również minimalny przykład, który odtwarza problem: http://sscce.org/ –

+0

OK, zaktualizowałem pytanie za pomocą stacktrace inline.but Nie mam odtwarzalnego przykładu, ponieważ zdarza się od czasu do czasu. może trochę jak na 100k zindeksowanych stron, a może nawet mniej. Nie jest to coś, co można łatwo odtworzyć, a cały plik stacktrace z kodem bibliotek nie jest moim kodem, więc nie mam pojęcia, jak zrobić minimalny przykład. – Aldarund

Odpowiedz

5

Na pierwszy rzut oka wydaje się, że jest to spowodowane błędem w scrapy. Scrapy definiuje własną skręconą "fabrykę kontekstu": https://github.com/scrapy/scrapy/blob/ad36de4e6278cf635509a1ade30cca9a506da682/scrapy/core/downloader/contextfactory.py#L21-L28

Ten kod tworzy instancję ClientTLSOptions z kontekstem, który zamierza zwrócić. Efektem ubocznym tworzenia tej klasy jest to, że "callback informacji" jest zainstalowany w fabryce kontekstu. Oddzwanianie informacji wymaga, aby implementacja Twisted TLS została ustawiona jako "dane aplikacji" w połączeniu. Jednak ponieważ nic nie używa instancji ClientTLSOptions (jest ona natychmiast odrzucana), dane aplikacji nigdy nie są ustawiane.

Gdy zwrot informacji wraca, aby uzyskać implementację Twisted TLS (niezbędną do wykonania części zadania), zamiast tego stwierdza, że ​​nie ma danych aplikacji i kończy się niepowodzeniem z zgłoszonym wyjątkiem.

Efekt uboczny z ClientTLSOptions jest trochę nieprzyjemny, ale myślę, że jest to wyraźnie błąd związany ze złomowaniem spowodowany niewłaściwym użyciem/nadużyciem ClientTLSOptions. Nie sądzę, aby ten kod mógł być bardzo dobrze przetestowany, ponieważ ten błąd wystąpi za każdym razem, gdy certyfikat nie potwierdzi.

Sugeruję zgłoszenie błędu do Scrapy. Mam nadzieję, że mogą naprawić ich użycie z ClientTLSOptions i wyeliminować ten błąd dla ciebie.

21

udało mi się rozwiązać ten problem, instalując pakiet service_identity:

pip install service_identity

+5

Rozwiązano problem. Dziękuję Ci. – thedp

+1

Co to za czary! Ten sam błąd, naprawiłem go od razu. Dzięki –

+0

nic mi się nie zmienia – Aldarund

0

udało mi się rozwiązać ten problem przez zastąpienie https: // http: // we wszystkich linków obraz przed wysłaniem je do imagepipeline