문제

말하고 싶습니다 urllib2.urlopen (또는 a 사용자 정의 오프너) 사용 127.0.0.1 (또는 ::1) 주소를 해결하기 위해. 나는 내 변화를 바꾸지 않을 것이다 /etc/resolv.conf, 하지만.

가능한 해결책 중 하나는와 같은 도구를 사용하는 것입니다 dnspython 쿼리 주소 및 httplib 사용자 정의 URL 오프너를 구축합니다. 나는 말하는 것을 선호한다 urlopen 그래도 사용자 정의 네임 서버를 사용합니다. 제안이 있습니까?

도움이 되었습니까?

해결책

이름 해상도가 궁극적으로 처리되는 것 같습니다 socket.create_connection.

-> urllib2.urlopen
-> httplib.HTTPConnection
-> socket.create_connection

"호스트 :"헤더가 설정되면 호스트를 해결하고 IP 주소를 오프너로 전달할 수 있습니다.

나는 당신이 서브 클래스를 제안합니다 httplib.HTTPConnection, 그리고 랩 connect 수정 방법 self.host 전달하기 전에 socket.create_connection.

그런 다음 서브 클래스 HTTPHandler (그리고 HTTPSHandler) 교체합니다 http_open 당신의 통과하는 방법 HTTPConnection httplib 대신에 do_open.

이와 같이:

import urllib2
import httplib
import socket

def MyResolver(host):
  if host == 'news.bbc.co.uk':
    return '66.102.9.104' # Google IP
  else:
    return host

class MyHTTPConnection(httplib.HTTPConnection):
  def connect(self):
    self.sock = socket.create_connection((MyResolver(self.host),self.port),self.timeout)
class MyHTTPSConnection(httplib.HTTPSConnection):
  def connect(self):
    sock = socket.create_connection((MyResolver(self.host), self.port), self.timeout)
    self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)

class MyHTTPHandler(urllib2.HTTPHandler):
  def http_open(self,req):
    return self.do_open(MyHTTPConnection,req)

class MyHTTPSHandler(urllib2.HTTPSHandler):
  def https_open(self,req):
    return self.do_open(MyHTTPSConnection,req)

opener = urllib2.build_opener(MyHTTPHandler,MyHTTPSHandler)
urllib2.install_opener(opener)

f = urllib2.urlopen('http://news.bbc.co.uk')
data = f.read()
from lxml import etree
doc = etree.HTML(data)

>>> print doc.xpath('//title/text()')
['Google']

분명히 HTTPS를 사용하는 경우 인증서 문제가 있으며 Myresolver를 작성해야합니다 ...

다른 팁

또 다른 (더러운) 방식은 원숭이 패치입니다 socket.getaddrinfo.

예를 들어이 코드는 DNS 조회에 대한 (무제한) 캐시를 추가합니다.

import socket
prv_getaddrinfo = socket.getaddrinfo
dns_cache = {}  # or a weakref.WeakValueDictionary()
def new_getaddrinfo(*args):
    try:
        return dns_cache[args]
    except KeyError:
        res = prv_getaddrinfo(*args)
        dns_cache[args] = res
        return res
socket.getaddrinfo = new_getaddrinfo

자신의 DNS 조회 클라이언트 (또는 DNSPython 사용)를 구현해야합니다. GLIBC의 이름 조회 절차는 다른 비 DNS 이름 시스템과의 호환성을 보장하기 위해 매우 복잡합니다. 예를 들어 GLIBC 라이브러리에 특정 DNS 서버를 지정할 방법이 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top