使用 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)
不知道是否有经验的同学能不能帮一下忙。谢谢!
1
SuperFashi 2016-07-31 12:38:25 +08:00 via Android
首先我推荐 requests 库。
看起来是没有问题的,不过有一些小地方问你一下,为啥 head 里面钦定了 Content-Length ,还有你确定后面没有动到 head 吗?推荐你在 post 之前先输出一下 head 。 |
2
matthewgao 2016-07-31 17:30:17 +08:00
你用的是 HTTPCookieProcessor , Content-Type 并不是 cookie 的一部分
|
3
mikulch OP @SuperFashi
req = request.Request(self.hotel_search_url, data=parsed_request_data, headers=self.head) 最后我用这样的方式解决了问题。 奇怪的是, openner.addheaders 设置了以后,实际上根本没有作用。通过 openner.open 发出去的请求,全部都是带有默认的 http header 的请求。。。实在是不知道原因是什么。 |
4
mikulch OP @matthewgao 我是看了官方文档
https://docs.python.org/3/library/urllib.request.html 才这么做的。 但是官方文档使用的是默认的 openBuilder 。也就是说,使用 httpCookieProcessor 的时候, addheader 实际上并没有生效么。。。 |
5
mikulch OP @SuperFashi sorry
我又看了一次 使用 openner.open 这个 api 的时候,会自动的生成默认的几个 header 。 其他的 header 是可以设置的。 使用 opener.open 这个 api 的时候 content-type 会默认变成 application/x-www-form-urlencoded 。 |
6
matthewgao 2016-07-31 18:05:17 +08:00
@mikulch 我觉得可能会被覆盖掉,我没有特别细的看 document ,但是看起来你没有操作任何 cookies 相关的,所以是不是用 HTTPHandler 就可以呢
|