2016-12-06 30 views
0

私はPython 2.7でシンプルなWebクローラーを作成していますが、HTTPS Webサイトから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証明書を検証するためにプログラムをその方向に向けることができましたが、理想的には自分のプログラムが「オフザボックス」で動作するようにしたいと思っています。それを使っている人。誰も何をすべきか考えていますか?

編集:私は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を使用するようにプログラムを変更しましたが、それは無関係です。

関連する問題