【问题标题】:Get a header with Python and convert in JSON (requests - urllib2 - json)使用 Python 获取标头并转换为 JSON(请求 - urllib2 - json)
【发布时间】:2014-08-23 08:33:20
【问题描述】:

我正在尝试从网站获取标题,将其编码为 JSON 以将其写入文件。 我尝试了两种不同的方法,但都没有成功。

首先使用 urllib2 和 json

import urllib2
import json
host = ("https://www.python.org/")
header = urllib2.urlopen(host).info()
json_header = json.dumps(header)
print json_header

这样我得到错误:

类型错误:不是 JSON可序列化

所以我尝试通过将对象转换为字符串来绕过这个问题 -> json_header = str(header) 这样我可以 json_header = json.dumps(header) 但输出很奇怪:

“日期:格林威治标准时间 2014 年 7 月 2 日星期三 13:33:37\r\n服务器:nginx\r\n内容类型: 文本/html; charset=utf-8\r\nX-Frame-选项: SAMEORIGIN\r\nContent-Length: 45682\r\nAccept-Ranges: bytes\r\nVia: 1.1 清漆\r\n年龄: 1263\r\nX-Served-By: cache-fra1220-FRA\r\nX-Cache: HIT\r\nX-Cache-Hits: 2\r\nVary: Cookie\r\nStrict -运输安全: 最大年龄=63072000; includeSubDomains\r\n连接:关闭\r\n"

第二个请求

import requests
r = requests.get(“https://www.python.org/”)
rh = r.headers
print rh

{'content-length': '45682', 'via': '1.1 varnish', 'x-cache': 'HIT', “接受范围”:“字节”,“严格传输安全”: '最大年龄=63072000; includeSubDomains', 'vary': 'Cookie', 'server': 'nginx','x-served-by':'cache-fra1226-FRA','x-cache-hits':'14', “日期”:“格林威治标准时间 2014 年 7 月 2 日星期三 13:39:33”,“x-frame-options”: 'SAMEORIGIN', '内容类型': 'text/html;字符集=utf-8','年龄': '1619'}

通过这种方式,输出更像 JSON,但仍然不正常(请参阅“”而不是“”和其他东西,如 = 和 ;)。 显然有些事情(或很多)我做得不对。 我试图阅读模块的文档,但我不明白如何解决这个问题。 感谢您的帮助。

【问题讨论】:

    标签: python json python-2.7 urllib2 python-requests


    【解决方案1】:

    将标头编码为JSON 的方法不止几种,但我的第一个想法是将headers 属性转换为实际字典,而不是作为requests.structures.CaseInsensitiveDict 访问它

    import requests, json
    r = requests.get("https://www.python.org/")
    rh = json.dumps(r.headers.__dict__['_store'])
    print rh
    

    {'content-length': ('content-length', '45474'), 'via': ('via', '1.1 清漆'),'x-cache':('x-cache','HIT'),'accept-ranges': ('accept-ranges', 'bytes'), 'strict-transport-security': ('strict-transport-security', 'max-age=63072000; includeSubDomains'), 'vary': ('vary', 'Cookie'), 'server': ('server', 'nginx'), 'x-served-by': ('x-served-by', 'cache-iad2132-IAD'), 'x-cache-hits': ('x-cache-hits', '1'), 'date': ('date', 'Wed, 02 Jul 2014 14:13:37 GMT'), 'x-frame-options': ('x-frame-options', 'SAMEORIGIN'), “内容类型”:(“内容类型”,“文本/html;字符集=utf-8”),“年龄”: ('年龄', '1483')}

    根据您对标题的确切要求,您可以在此之后专门访问它们,但这将为您提供标题中包含的所有信息,如果格式略有不同。

    如果您喜欢不同的格式,也可以将标题转换为字典:

    import requests, json
    r = requests.get("https://www.python.org/")
    print json.dumps(dict(r.headers))
    

    {“content-length”:“45682”,“via”:“1.1 varnish”,“x-cache”:“HIT”, “接受范围”:“字节”,“严格传输安全”: "max-age=63072000; includeSubDomains", "vary": "Cookie", "server": “nginx”、“x-served-by”:“cache-at50-ATL”、“x-cache-hits”:“5”、“日期”: “格林威治标准时间 2014 年 7 月 2 日星期三 14:08:15”,“x-frame-options”:“SAMEORIGIN”, "content-type": "text/html; charset=utf-8", "age": "951"}

    【讨论】:

    • 非常感谢@Slater Tyranus。你的第二种方法正是我想要的。只是出于好奇提出一个问题。阅读您的第一个方法的输出,我看到键和值在“”内。为什么 json.dumps 在这种情况下会这样做?有效的 JSON 格式是否应该在“”中包含值?
    【解决方案2】:
    import requests
    import json
    
    r = requests.get('https://www.python.org/')
    rh = r.headers
    
    print json.dumps( dict(rh) ) # use dict()
    

    结果:

    {"content-length": "45682", "via": "1.1 varnish", "x-cache": "HIT", "accept-ranges": "bytes", "strict-transport-security" :“max-age=63072000;includeSubDomains”、“vary”:“Cookie”、“server”:“nginx”、“x-served-by”:“cache-fra1224-FRA”、“x-cache-hits” :“5”,“日期”:“格林威治标准时间 2014 年 7 月 2 日星期三 14:08:04”,“x-frame-options”:“SAMEORIGIN”,“content-type”:“text/html; charset=utf- 8", "年龄": "3329"}

    【讨论】:

    • 感谢您的帮助@furas
    【解决方案3】:

    如果您只对标头感兴趣,请发出head 请求。将CaseInsensitiveDict 转换为dict 对象,然后将其转换为json。

    import requests
    import json
    r = requests.head('https://www.python.org/')
    rh = dict(r.headers)
    json.dumps(rh)
    

    【讨论】:

      【解决方案4】:

      我知道这是一个老问题,但我在尝试组合一个快速而肮脏的 Python curl-esque URL getter 时偶然发现了它。我一直收到错误:

      TypeError: Object of type 'CaseInsensitiveDict' is not JSON serializable
      

      如果需要立即输出 JSON 字符串,上述解决方案很好,但在我的情况下,我需要返回标题的 python 字典,并且我想规范化大写以使所有键都小写。

      我的解决方案是使用dict comprehension:

      import requests
      
      response = requests.head('https://www.python.org/')
      
      my_dict = {
         'body': response.text,
         'http_status_code': response.status_code,
         'headers': {k.lower(): v for (k, v) in response.headers.items()}
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-05-17
        • 2011-09-14
        • 2018-02-04
        • 2020-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多