2016-12-06 1 views
0

Python 2.7에서 간단한 웹 크롤러를 작성 중이며 HTTPS 웹 사이트에서 robots.txt 파일을 검색 할 때 SSL 인증서 확인 실패 예외가 발생합니다.RobotParser가 SSL 인증서를 확인하지 못했습니다. 예외가 발생했습니다.

가 여기에 관련 코드입니다 :

def getHTMLpage(pagelink, currenttime): 
    "Downloads HTML page from server" 
    #init 
    #parse URL and get domain name 
    o = urlparse.urlparse(pagelink,"http") 
    if o.netloc == "": 
     netloc = re.search(r"[^/]+\.[^/]+\.[^/]+", o.path) 
     if netloc: 
      domainname="http://"+netloc.group(0)+"/" 
    else: 
     domainname=o.scheme+"://"+o.netloc+"/" 
    if o.netloc != "" and o.netloc != None and o.scheme != "mailto": #if netloc isn't empty and it's not a mailto link 
     link=domainname+o.path[1:]+o.params+"?"+o.query+"#"+o.fragment 
     if not (robotfiledictionary.get(domainname)): #if robot file for domainname was not downloaded 
      robotfiledictionary[domainname] = robotparser.RobotFileParser() #initialize robots.txt parser 
      robotfiledictionary[domainname].set_url(domainname+"robots.txt") #set url for robots.txt 
      print " Robots.txt for %s initial download" % str(domainname) 
      robotfiledictionary[domainname].read() #download/read robots.txt 
     elif (robotfiledictionary.get(domainname)): #if robot file for domainname was already downloaded 
      if (currenttime - robotfiledictionary[domainname].mtime()) > 3600: #if robot file is older than 1 hour 
       robotfiledictionary[domainname].read() #download/read robots.txt 
       print " Robots.txt for %s downloaded" % str(domainname) 
       robotfiledictionary[domainname].modified() #update time 
     if robotfiledictionary[domainname].can_fetch("WebCrawlerUserAgent", link): #if access is allowed... 
      #fetch page 
      print link 
      page = requests.get(link, verify=False) 
      return page.text() 
     else: #otherwise, report 
      print " URL disallowed due to robots.txt from %s" % str(domainname) 
      return "URL disallowed due to robots.txt" 
    else: #if netloc was empty, URL wasn't parsed. report 
     print "URL not parsed: %s" % str(pagelink) 
     return "URL not parsed" 

그리고 여기에 내가 갖는 예외입니다 :

Robots.txt for https://ehi-siegel.de/ initial download 
Traceback (most recent call last): 
    File "C:\webcrawler.py", line 561, in <module> 
    HTMLpage = getHTMLpage(link, loopstarttime) 
    File "C:\webcrawler.py", line 122, in getHTMLpage 
    robotfiledictionary[domainname].read() #download/read robots.txt 
    File "C:\Python27\lib\robotparser.py", line 58, in read 
    f = opener.open(self.url) 
    File "C:\Python27\lib\urllib.py", line 213, in open 
    return getattr(self, name)(url) 
    File "C:\Python27\lib\urllib.py", line 443, in open_https 
    h.endheaders(data) 
    File "C:\Python27\lib\httplib.py", line 1053, in endheaders 
    self._send_output(message_body) 
    File "C:\Python27\lib\httplib.py", line 897, in _send_output 
    self.send(msg) 
    File "C:\Python27\lib\httplib.py", line 859, in send 
    self.connect() 
    File "C:\Python27\lib\httplib.py", line 1278, in connect 
    server_hostname=server_hostname) 
    File "C:\Python27\lib\ssl.py", line 353, in wrap_socket 
    _context=self) 
    File "C:\Python27\lib\ssl.py", line 601, in __init__ 
    self.do_handshake() 
    File "C:\Python27\lib\ssl.py", line 830, in do_handshake 
    self._sslobj.do_handshake() 
IOError: [Errno socket error] [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590) 

당신이 볼 수 있듯이, 난 이미를 검색하기 위해 끝 부분에 코드를 변경했습니다 SSL 인증서를 무시한 페이지 (프로덕션 환경에서 당황 스럽지만 테스트하고 싶었습니다)가되었지만 이제는 robotparser.read() 함수가 SSL 검증에 실패했습니다. 인증서를 수동으로 다운로드하고 SSL 인증서를 확인하기 위해 프로그램을 그 방향으로 향하게하는 것을 보았습니다.하지만 개인적으로는 내가 될 수 없기 때문에 "off-the-box"로 프로그램 작업을하고 싶습니다. 그것을 사용하는 사람. 누구든지 무엇을 해야할지 알 수 있습니까?

편집 : 나는 robotparser.py를 방문했습니다. 나는

import requests 

을 추가

f = requests.get(self.url, verify=False) 

에 라인 (58)을 변경하고이 그것을 해결 한 것으로 보인다. 이것은 여전히 ​​이상적이지 않기 때문에, 나는 무엇을 해야할지에 대한 제안을 여전히하고 있습니다.

답변

0

해결책을 직접 찾았습니다. urllib3의 요청 기능을 사용하여 모든 웹 사이트를 인증하고 계속 액세스 할 수있었습니다.

여전히 robotparser.py 파일을 편집해야했습니다. 이것은 내가 처음으로 추가 된 것입니다 :

import urllib3 
import urllib3.contrib.pyopenssl 
import certifi 
urllib3.contrib.pyopenssl.inject_into_urllib3() 
http = urllib3.PoolManager(cert_reqs="CERT_REQUIRED", ca_certs=certifi.where()) 

그리고 이것은 (자기) 읽기의 정의입니다 :

def read(self): 
    """Reads the robots.txt URL and feeds it to the parser.""" 
    opener = URLopener() 
    f = http.request('GET', self.url) 
    lines = [line.strip() for line in f.data] 
    f.close() 
    self.errcode = opener.errcode 
    if self.errcode in (401, 403): 
     self.disallow_all = True 
    elif self.errcode >= 400 and self.errcode < 500: 
     self.allow_all = True 
    elif self.errcode == 200 and lines: 
     self.parse(lines) 

가 나는 또한 내 프로그램의 기능에 실제 페이지 요청을 얻기 위해 동일한 프로세스를 사용 :

def getHTMLpage(pagelink, currenttime): 
    "Downloads HTML page from server" 
    #init 
    #parse URL and get domain name 
    o = urlparse.urlparse(pagelink,u"http") 
    if o.netloc == u"": 
     netloc = re.search(ur"[^/]+\.[^/]+\.[^/]+", o.path) 
     if netloc: 
      domainname=u"http://"+netloc.group(0)+u"/" 
    else: 
     domainname=o.scheme+u"://"+o.netloc+u"/" 
    if o.netloc != u"" and o.netloc != None and o.scheme != u"mailto": #if netloc isn't empty and it's not a mailto link 
     link=domainname+o.path[1:]+o.params+u"?"+o.query+u"#"+o.fragment 
     if not (robotfiledictionary.get(domainname)): #if robot file for domainname was not downloaded 
      robotfiledictionary[domainname] = robotparser.RobotFileParser() #initialize robots.txt parser 
      robotfiledictionary[domainname].set_url(domainname+u"robots.txt") #set url for robots.txt 
      print u" Robots.txt for %s initial download" % str(domainname) 
      robotfiledictionary[domainname].read() #download/read robots.txt 
     elif (robotfiledictionary.get(domainname)): #if robot file for domainname was already downloaded 
      if (currenttime - robotfiledictionary[domainname].mtime()) > 3600: #if robot file is older than 1 hour 
       robotfiledictionary[domainname].read() #download/read robots.txt 
       print u" Robots.txt for %s downloaded" % str(domainname) 
       robotfiledictionary[domainname].modified() #update time 
     if robotfiledictionary[domainname].can_fetch("WebCrawlerUserAgent", link.encode('utf-8')): #if access is allowed... 
      #fetch page 
      if domainname == u"https://www.otto.de/" or domainname == u"http://www.otto.de": 
       driver.get(link.encode('utf-8')) 
       time.sleep(5) 
       page=driver.page_source 
       return page 
      else: 
       page = http.request('GET',link.encode('utf-8')) 
       return page.data.decode('UTF-8','ignore') 
     else: #otherwise, report 
      print u" URL disallowed due to robots.txt from %s" % str(domainname) 
      return u"URL disallowed due to robots.txt" 
    else: #if netloc was empty, URL wasn't parsed. report 
     print u"URL not parsed: %s" % str(pagelink) 
     return u"URL not parsed" 

또한 프로그램을 엄격하게 UTF-8로 변경했는데 관련이 없습니다.

관련 문제