Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 告诉urllib2使用自定义DNS_Python_Dns_Urllib2_Dnspython_Urlopen - Fatal编程技术网

Python 告诉urllib2使用自定义DNS

Python 告诉urllib2使用自定义DNS,python,dns,urllib2,dnspython,urlopen,Python,Dns,Urllib2,Dnspython,Urlopen,我想告诉urlib2.urlopen(或自定义开启器)使用127.0.0.1(或::1)解析地址。但是,我不会更改我的/etc/resolv.conf 一种可能的解决方案是使用类似于dnspython的工具来查询地址,并使用httplib来构建自定义url开启器。不过,我更愿意告诉urlopen使用自定义名称服务器。有什么建议吗?看起来名称解析最终由套接字处理。创建\u连接 -> urllib2.urlopen -> httplib.HTTPConnection -> sock

我想告诉
urlib2.urlopen
(或自定义开启器)使用
127.0.0.1
(或
::1
)解析地址。但是,我不会更改我的
/etc/resolv.conf


一种可能的解决方案是使用类似于
dnspython
的工具来查询地址,并使用
httplib
来构建自定义url开启器。不过,我更愿意告诉
urlopen
使用自定义名称服务器。有什么建议吗?

看起来名称解析最终由
套接字处理。创建\u连接

-> urllib2.urlopen
-> httplib.HTTPConnection
-> socket.create_connection
虽然一旦设置了“Host:”头,您就可以解析主机并将IP地址向下传递到开场白

我建议您在将
httplib.HTTPConnection
传递到
socket.create\u connection
之前,将
connect
方法包装成子类,以修改
self.host

-> urllib2.urlopen
-> httplib.HTTPConnection
-> socket.create_connection
然后子类
HTTPHandler
(和
HTTPSHandler
)将
http\u open
方法替换为将您的
HTTPConnection
而不是httplib自己的方法传递给
do\u 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…

您需要实现自己的dns查找客户端(或如您所说使用dnspython)。glibc中的名称查找过程非常复杂,以确保与其他非dns名称系统的兼容性。例如,根本没有办法在glibc库中指定特定的DNS服务器。

另一种(肮脏的)方法是monkey patching
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

我想我现在不需要HTTPS,所以这就足够了!非常感谢你!还可以覆盖
HTTPConnection.\u create\u connection
,这是从Python 2.7.7和3.5开始提供的,因为。这种攻击的一个优点是,它还可以拦截Python中几乎所有的dns查找,而不仅仅是通过
urlopen
这是一个更好的解决方案,如果主机的作用域是一个较小的数目。我的速度提高了10倍。:)