2013-10-02 32 views
1

我創建了一個Python項目來測試谷歌地圖API。我測試第一個API時發生了問題:附近的搜索請求。爲什麼我無法使用Google Map API獲取完整的數據?

我試圖提供這個網址的官方文檔: https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=500&types=food&name=harbour&sensor=false&key=AddYourOwnKeyHere 如果我把這個網址在我的瀏覽器,我會在瀏覽器中完美的數據。然後,我什麼也沒做,但創造一個Python模塊,這裏是代碼:

if __name__ == '__main__': 

import socket 
import ssl 


sock = ssl.wrap_socket(socket.socket()) 
sock.connect(('maps.googleapis.com', 443)) 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.connect(('maps.googleapis.com', 443)) 
sslSocket = socket.ssl(s) 
uri = 'GET /maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=500&sensor=false&key=MyKey HTTP/1.1\r\nHost:maps.googleapis.com\r\nContent-Type: application/json; charset=UTF-8\r\naccept-encoding:gzip,deflate,sdch\r\n\r\n' 
sslSocket.write(uri) 

data = sock.read() 
print 'going to connect...' 
print data 
s.close() 

不幸的是,我得到了控制檯上的結果是這樣的:

going to connect... 
HTTP/1.1 200 OK 
Content-Type: application/json; charset=UTF-8 
Date: Wed, 02 Oct 2013 08:05:59 GMT 
Expires: Wed, 02 Oct 2013 08:10:59 GMT 
Cache-Control: public, max-age=300 
Vary: Accept-Language 
Server: mafe 
X-XSS-Protection: 1; mode=block 
X-Frame-Options: SAMEORIGIN 
Alternate-Protocol: 443:quic 
Transfer-Encoding: chunked 

560b 
{ 
"debug_info" : [], 
"html_attributions" : [ 
"Listings by \u003ca href=\"http://www.yellowpages.com.au/\"\u003eYellow   Pages\u003c/a\u003e"], 
"next_page_token" : "ClRHAAAA4lOaMlZcUjyndIqhBsHzyyU0nD5PHarmjgmnguj3morn7Em- ipqhSR33V__d0kjrL4PzAqY7y4TAK7Uj3XzWjhoUchLBcBs- TNFxWIvGst8SEArmj_T7_eDZWyr8UDGy5OEaFPFaK2yHDg7Kv2U3Obsy7opkQfEw", 
"results" : [ 
{ 
"geometry" : { 
"location" : { 
"lat" : -33.8599827, 
"lng" : 151.2021282 
}, 
"viewport" : { 
"northeast" : { 
"lat" : -33.8552584, 
"lng" : 151.2031401 
}, 

這個結果是不完整的,我試過很多次,結果是一樣的。那麼,如何解決這個問題呢?

+0

直到我不知道這是否與谷歌地圖API –

+2

的https協議你爲什麼不使用這樣的東西'urllib'或相關[ Python請求](http://docs.python-requests.org/en/latest/)用於發出HTTP請求?我從來沒有見過任何人使用套接字與HTTP服務交談。 –

回答

1

問題是,您正在使用套接字HTTP。具體而言,sock.read()不保證讀取對方發送的所有字節;相反,你必須不斷詢問它,直到它返回一個空字節字符串。那麼你可以確定你已經收到了一切。但是,套接字非常棘手,使用它們幾乎不是一個好主意,而且選擇更高級別的框架幾乎總是一個好主意。例如,即使ssl_sock.write()實際上甚至可能不會寫入所有內容(或至少sock.send()肯定會以這種方式運行),而是返回發送的字節數,如果該值小於傳遞給它的數據,則必須重試其餘部分(未發送的)數據。

現在,用HTTP,我從來沒有見過任何人使用套接字。請使用urllib2或更好的urllib2.urlopen(...)Python Requests。此外,還有urllibhttplib。例如,Python的請求,你的代碼變得簡單:

import requests 

response = requests.get('https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=500&sensor=false&key=MyKey') 
data = response.json() # shortcut to `import json; json.loads(response.text)` 

最簡單的方法來安裝Python的要求是pip install requests(或easy_install requests)。或者,如果你寧願希望避免依賴關係:

import json 
import urllib 

data_raw = urllib.urlopen('https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=500&sensor=false&key=MyKey').read() 
data = json.loads(data_raw) 

而現在,data保證包含整個效應初探;你永遠不會得到部分答覆。

P.S.如果你需要隨着你的要求有些HTTP請求頭傳遞,你也可以這樣做:

requests.get(url, headers={...}) 

P.P.S.,如果你想了解更多有關原始套接字(希望只對非HTTP的目的),見Python的Socket Programming HOWTO

+0

謝謝你的接吻。我嘗試了你的方式,並獲得完整的數據。我只使用套接字的原因是我不能保證我使用的服務器可以很好地與其他的lib一起工作。 –

+0

@VincentWang:不需要這樣的保證:如果它是一個HTTP/HTTPS服務器,它將**與HTTP客戶端庫一起工作,特別是因爲它是一個Google服務器 - 沒有理由懷疑Google不符合HTTP標準。 –

0

help(sock.read)得出:在方法

幫助模塊SSL閱讀:

讀取(self,len = 1024)ssl.SSLSocket實例的方法 最多讀取LEN個字節並返回它們。 在EOF上返回零長度字符串。

,你的反應是接近1024個字符這樣試試:

data = ' ' 
while len(data) > 0: 
    data = sock.read() 
    print data, 
print "\nDone." 
+0

雖然在技術上是正確的,但我認爲這不是一個好主意,可以幫助初學者使用原始套接字製作HTTPS請求:)他很快會回來並請求幫助解析頭文件和類似的東西;所以除非學習HTTP的內部機制,否則對他來說可能不是好事。 –

+1

已經足夠了__but__,因爲OP已經提出了原始請求...(這就是爲什麼我已經爲你的答案+1了,當我貼我的時候)。 –

-1

第一anwser涼爽。但有時你必須使用原始套接字來解決問題......

所以我使用的代碼試了一下我的API密鑰下面

data = ' ' 
while len(data) > 0: 
    data = sock.read() 
    print data, 
    print len(data) 
print "\nDone." 

而有時數據的長度爲1024個,有時是381,我不知道爲什麼。另外,該程序不會跳出循環,這也讓我感到困惑。

P.S.任何人都可以解釋,在響應內容開始時的「560b」意味着什麼,非常感謝。

+0

-1從現有答案+問題複製粘貼+承認你不明白真正發生了什麼。 –

0

數據在多個發送和接收中發送。 所以,你應該運行一個循環來檢查時,數據帶有

receivedString = "" 
While True: 
    data = socket.recv(1024) #max length 1024 
    #time.sleep(0.25) 
    if(len(data) < 1): 
     break 
    recievedString = recievedString + data 
相關問題