2013-08-02 82 views
4

我正在使用python運行腳本,它使用urllib2從天氣api獲取數據並將其顯示在屏幕上。我有問題,當我查詢服務器時,我得到一個「沒有與主機名關聯的地址」錯誤。我可以使用Web瀏覽器查看api的輸出,並且可以使用wget下載該文件,但我必須強制IPv4才能使其工作。使用urllib2.urlopen時,是否可以在urllib2中強制使用IPv4?Python urllib2 force IPv4

回答

9

不直接,沒有。

那麼,你可以做什麼?


一種可能性是自己明確地將主機名解析爲IPv4,然後使用IPv4地址而不是名稱作爲主機。例如:

host = socket.gethostbyname('example.com') 
page = urllib2.urlopen('http://{}/path'.format(host)) 

然而,一些虛擬服務器站點可能需要Host: example.com頭,他們反而會得到一個Host: 93.184.216.119。您可以解決這通過重寫頭:

host = socket.gethostbyname('example.com') 
request = urllib2.Request('http://{}/path'.format(host), 
          headers = {'Host': 'example.com'}) 
page = urllib2.urlopen(request) 

或者,您也可以代替標準的人提供自己的處理程序。但標準處理程序大多隻是圍繞httplib.HTTPConnection的包裝,而真正的問題在於HTTPConnection.connect

所以,乾淨的方式做,這是創建自己的httplib.HTTPConnection子類,它覆蓋connect這樣的:

def connect(self): 
    host = socket.gethostbyname(self.host) 
    self.sock = socket.create_connection((host, self.post), 
             self.timeout, self.source_address) 
    if self._tunnel_host: 
     self._tunnel() 

然後創建自己的urllib2.HTTPHandler重寫http_open使用你的子類的子類:

def http_open(self, req): 
    return self.do_open(my wrapper.MyHTTPConnection, req) 

...同樣地,對於HTTPSHandler,然後適當地鉤出來的東西如圖所示urllib2文檔。

快速&骯髒的方式做同樣的事情只是monkeypatch httplib.HTTPConnection.connect以上功能。


最後,您可以使用不同的庫而不是urllib2。從我記得,requests並沒有使這更容易(最終,你必須重寫或monkeypatch略有不同的方法,但它是有效的相同)。但是,任何libcurl包裝將允許您執行相當於curl_easy_setopt(h, CURLOPT_IPRESOLVE, CURLOPT_IPRESOLVE_V4)

+0

是套接字的一類urllib2? – TheDoctor

+0

@TheDoctor:否,['socket'](http://docs.python.org/2/library/socket.html)是一個模塊,'socket.socket'是'socket'模塊的一個類。 – abarnert

+0

我已經得到它使用套接字,但現在我得到HTTP錯誤596:REST服務不可用。我不知道如何解決這個問題,不過謝謝 – TheDoctor