2014-01-08 4 views
1

Скажем, у меня есть следующий запрос HTTP:Python Извлечение JSON из HTTP Response

GET /4 HTTP/1.1 
Host: graph.facebook.com 

И сервер возвращает ответ:

HTTP/1.1 200 OK 
Access-Control-Allow-Origin: * 
Cache-Control: private, no-cache, no-store, must-revalidate 
Content-Type: text/javascript; charset=UTF-8 
ETag: "539feb8aee5c3d20a2ebacd02db380b27243b255" 
Expires: Sat, 01 Jan 2000 00:00:00 GMT 
Pragma: no-cache 
X-FB-Rev: 1070755 
X-FB-Debug: pC4b0ONpdhLwBn6jcabovcZf44bkfKSEguNsVKuSI1I= 
Date: Wed, 08 Jan 2014 01:22:36 GMT 
Connection: keep-alive 
Content-Length: 172 

{"id":"4","name":"Mark Zuckerberg","first_name":"Mark","last_name":"Zuckerberg","link":"http:\/\/www.facebook.com\/zuck","username":"zuck","gender":"male","locale":"en_US"} 

Поскольку заголовок Content-Lengh зависит от длины содержимого , Я не могу просто разбить строку Content-Length: 172. Как я могу извлечь JSON и заголовки отдельно? Они важны для моей программы. Я использую этот код, чтобы получить ответ:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.connect(("graph.facebook.com", 80)) 
s.send("GET /"+str(id)+"/picture HTTP/1.1\r\nHost: graph.facebook.com\r\n\r\n") 
data = s.recv(1024) 
s.close() 
json_string = (somehow extract this) 
userdata = json.loads(json_string) 
+1

split by '\ n \ n'? – tenub

+1

a) Не было бы это '\ r \ n \ r \ n' б) Я искал все это в одной строке и немного более изящно Но спасибо за предложение – 735Tesla

+0

зависит от вашего сервера os, но вы можете использовать оператор '|'. быстрый поиск в Google показывает [this] (http://stackoverflow.com/questions/1331815/regular-expression-to-match-cross-platform-newline-characters) – tenub

ответ

5

Простой способ сделать это состоит в использовании библиотеки HTTP. Например:

import json 
import urllib2 

r = urllib2.urlopen("http://graph.facebook.com/{}/picture".format(id)) 
json_string = r.read() 
userdata = json.loads(json_string) 

Если вы действительно хотите, чтобы разобрать его самостоятельно, то HTTP protocol гарантирует, что заголовки и тело разделены пустой строкой, и что это будет первая пустая строка где-нибудь в ответ, так что это не что трудно:

data = s.recv(1024) 
header, _, json_string = data.partition('\r\n\r\n') 
userdata = json.loads(json_string) 

есть некоторые очевидные вниз стороны к этому, как написано, что ваш код не будет работать, если ответ больше, чем 1K, или если ядро ​​не даст вам весь ответ в один recv (который он никогда не гарантирует), или если сервер перенаправляет вас или дает вам 100 ПРОДОЛЖЕНИЙ до реального ответ, или если сервер решает отправить обратно фрагментированный или MIME-multipart или другой ответ вместо плоского тела, или ...

+0

Какова цель ', _,' в 'header, _,'? – 735Tesla

+1

@ 735Tesla: ['str.partition'] (http://docs.python.org/2.7/library/stdtypes.html#str.partition) возвращает три значения: часть перед разделителем, разделитель и часть после разделителя. Часто вам не нужен средний (вы знаете, что это будет просто «\ r \ n \ r \ n'' здесь ...). Присвоение значений «не-уход» для '_' является распространенной идиомой в Python - достаточно читабельной, чтобы вы могли сказать, что там есть значение, но достаточно ненавязчивое, чтобы сигнализировать о том, что значение не имеет значения, кроме того, что оно указывает на его существование. – abarnert

+0

Спасибо, я никогда раньше не слышал об использовании '_'. +1 – 735Tesla

Смежные вопросы