如何使用 python3+urllib 发送一个 application/json 的请求?

2016-07-31 11:32:44 +08:00
 mikulch

使用 postman ,拼装好数据后采用 raw+application/json 的格式,发送 Post 请求能够被服务器正常接收。 通过截包工具 charles 工具,看到发出去的请求是 application/json 格式的数据。

但是采用 python3+urllib ,设置好 http 请求头的 contentType 为 application/json 格式以后,将参数通过 json.dumps 转换为 str 再 encode 成 bytes ,然后通过 openner 对象访问一个连接后,通过截包工具 charles 发现发出去的请求实际上是 application/x-www-form-urlencoded 的格式,请求虽然能成功但是服务器无法解析。

不太清楚这里内部处理是怎么一回事,不过尝试了很多方法, urllib 的包里我也没有看到能够直接把 dict 格式的数据作为参数的 api 。 postdata 都需要 bytes 格式的数据才行。

我的代码大概如下:


	head = {
        'Accept': '*/*',
        'Host': 'www.lvtufang.com',
        'Connection': 'keep-alive',
        'Content-Length': '245',
        'Origin': 'http://www.lvtufang.com',
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome'
                      '/51.0.2704.103 Safari/537.36',
        'Content-Type': 'application/json',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Referer': 'http://www.lvtufang.com/Account/Login?ReturnUrl=%2FHotel%2FFind',
        'Accept-Language': 'zh-CN,zh;q=0.8',
        'Accept-Encoding': 'gzip, deflate'
    }
    
		cookie = cookiejar.CookieJar()
        handler = urllib.request.HTTPCookieProcessor(cookie)
        opener = urllib.request.build_opener(handler)
        opener.addheader(head)
        # 其他为了获取 cookie 的各种请求。
        .....
        .....
        .....
        parsed_request_data = json.dumps(self.hotel_search_request_data).encode()
        response = openner.open(self.hotel_search_url, parsed_request_data)

不知道是否有经验的同学能不能帮一下忙。谢谢!

8854 次点击
所在节点    Python
6 条回复
SuperFashi
2016-07-31 12:38:25 +08:00
首先我推荐 requests 库。
看起来是没有问题的,不过有一些小地方问你一下,为啥 head 里面钦定了 Content-Length ,还有你确定后面没有动到 head 吗?推荐你在 post 之前先输出一下 head 。
matthewgao
2016-07-31 17:30:17 +08:00
你用的是 HTTPCookieProcessor , Content-Type 并不是 cookie 的一部分
mikulch
2016-07-31 17:46:28 +08:00
@SuperFashi
req = request.Request(self.hotel_search_url, data=parsed_request_data, headers=self.head)
最后我用这样的方式解决了问题。

奇怪的是, openner.addheaders 设置了以后,实际上根本没有作用。通过 openner.open 发出去的请求,全部都是带有默认的 http header 的请求。。。实在是不知道原因是什么。
mikulch
2016-07-31 17:49:51 +08:00
@matthewgao 我是看了官方文档
https://docs.python.org/3/library/urllib.request.html
才这么做的。
但是官方文档使用的是默认的 openBuilder 。也就是说,使用 httpCookieProcessor 的时候, addheader 实际上并没有生效么。。。
mikulch
2016-07-31 17:57:33 +08:00
@SuperFashi sorry
我又看了一次 使用 openner.open 这个 api 的时候,会自动的生成默认的几个 header 。
其他的 header 是可以设置的。
使用 opener.open 这个 api 的时候 content-type 会默认变成 application/x-www-form-urlencoded 。
matthewgao
2016-07-31 18:05:17 +08:00
@mikulch 我觉得可能会被覆盖掉,我没有特别细的看 document ,但是看起来你没有操作任何 cookies 相关的,所以是不是用 HTTPHandler 就可以呢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/296117

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX