2010-06-12 22 views
10

Tôi đang sử dụng chức năng urlopen để thử và nhận kết quả JSON từ api StackOverflow.Phá vỡ urlopen của Urllib trên một số trang web (ví dụ: StackApps api): trả về kết quả rác

Mã Tôi đang sử dụng:

>>> import urllib2 
>>> conn = urllib2.urlopen("http://api.stackoverflow.com/0.8/users/") 
>>> conn.readline() 

Kết quả tôi nhận được:

'\x1f\x8b\x08\x00\x00\x00\x00\x00\x04\x00\xed\xbd\x07`\x1cI\x96%&/m\xca{\x7fJ\... 

Tôi khá mới để urllib, nhưng điều này không có vẻ như kết quả tôi nên nhận được. Tôi đã thử nó ở những nơi khác và tôi nhận được những gì tôi mong đợi (giống như truy cập vào địa chỉ với một trình duyệt cho tôi: một đối tượng JSON).

Sử dụng urlopen trên các trang web khác (ví dụ: "http://google.com") hoạt động tốt và cung cấp cho tôi html thực tế. Tôi cũng đã thử sử dụng urllib và nó mang lại kết quả tương tự.

Tôi khá mắc kẹt, thậm chí không biết tìm cách giải quyết vấn đề này ở đâu. Ý tưởng nào?

+1

Cảm ơn! Điều này đã giúp tôi gỡ lỗi ứng dụng API của riêng tôi :) – swanson

Trả lời

10

Điều đó gần như trông giống như một thứ bạn sẽ cho chúng ăn. Có thể một cái gì đó trong chuỗi User-Agent hoặc Accepts header mà urllib2 đang gửi đang gây ra StackOverflow để gửi một cái gì đó khác với JSON.

Một câu hỏi là xem conn.headers.headers để xem tiêu đề Loại nội dung cho biết.

Và câu hỏi này, Odd String Format Result from API Call, có thể có câu trả lời của bạn. Về cơ bản, bạn có thể phải chạy kết quả của mình thông qua trình giải nén gzip.

kiểm tra đôi với mã này:

>>> req = urllib2.Request("http://api.stackoverflow.com/0.8/users/", 
          headers={'Accept-Encoding': 'gzip, identity'}) 
>>> conn = urllib2.urlopen(req) 
>>> val = conn.read() 
>>> conn.close() 
>>> val[0:25] 
'\x1f\x8b\x08\x00\x00\x00\x00\x00\x04\x00\xed\xbd\x07`\x1cI\x96%&/m\xca{\x7fJ' 

Vâng, bạn có chắc chắn nhận được dữ liệu gzip mã hóa lại.

Vì bạn dường như nhận được các kết quả khác nhau trên các máy khác nhau với cùng một phiên bản Python, và nói chung có vẻ như API urllib2 yêu cầu bạn làm điều gì đó đặc biệt để yêu cầu dữ liệu mã hóa gzip, tôi đoán là bạn có proxy trong suốt ở đó một nơi nào đó.

Tôi đã xem bản trình bày của EFF tại CodeCon năm 2009. Họ đã thực hiện kiểm tra kết nối đầu cuối để khám phá các thủ thuật ISP bẩn khác nhau. Một trong những điều mà họ phát hiện khi thực hiện thử nghiệm này là một số lượng đáng ngạc nhiên các bộ định tuyến NAT của người tiêu dùng thêm các tiêu đề HTTP ngẫu nhiên hoặc thực hiện proxy trong suốt. Bạn có thể có một số thiết bị trên mạng của bạn, đó là thêm hoặc sửa đổi tiêu đề Accept-Encoding để làm cho kết nối của bạn có vẻ nhanh hơn.

+0

Hmm, điều đó có ý nghĩa. Bất kỳ ý tưởng tại sao điều này sẽ khác nhau trên các máy tính khác nhau (chạy cùng một phiên bản Python)? –

+1

@Edan Maor: Tôi không biết. Nó có vẻ kỳ quặc với tôi. – Omnifarious

+0

Vâng, tôi vừa kiểm tra trên hệ thống của riêng mình và đó chắc chắn là vấn đề (tôi đã sử dụng hướng dẫn được tìm thấy trên http://diveintopython.org/http_web_services/gzip_compression.html để thử và giải nén). Vẫn không có ý tưởng tại sao điều này chỉ xảy ra với tôi, vì nó hoạt động tốt cho các nhà phát triển khác ở đây, và dường như hoạt động tốt cho tác giả của wrapper là tốt. –