Python爬虫使用requests库post方法抓取汇率数据失败,请教原因
想从这个网站上获取人民币对美元的汇率, http://forex.jrj.com.cn/
跟踪调试的过程,发现是由这个链接获取的, http://quote1.fx168.com/jrj/CurrencyConvert/ajaxpro/CurrencyConvert.ConvertJrj,jrj.ashx
如下是我的代码 header, formdata 复制的原请求,
# -*- coding: utf-8 -*-
import requests
import json
def get_exchange():
headers = {
‘Accept’: ‘/’,
‘Accept-Encoding’: ‘gzip, deflate’,
‘Accept-Language’: ‘en,zh-CN;q=0.9,zh;q=0.8,en-US;q=0.7,ja;q=0.6’,
‘Ajax-method’: ‘Calculate’,
‘Connection’: ‘keep-alive’,
‘Content-Length’: ‘56’,
‘Content-Type’: ‘application/x-www-form-urlencoded’,
‘Host’: ‘quote1.fx168.com’,
‘Origin’: ‘http://quote1.fx168.com’,
‘Referer’: ‘http://quote1.fx168.com/Jrj/CurrencyConvert/ConvertJrj3.aspx’,
‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36’,
}
testUrl = ‘http://quote1.fx168.com/jrj/CurrencyConvert/ajaxpro/CurrencyConvert.ConvertJrj,jrj.ashx’
submit_data = {“moneys”: “1”, “start”: “美元”, “end”: “人民币”}
response = requests.post(testUrl, headers=headers, data=submit_data)
print(response.content)
if name == ‘main’:
get_exchange()
但是输入的结果却不对,
b'"word m"'
不知道我的代码问题在哪里, 请教一下。
Python爬虫使用requests库post方法抓取汇率数据失败,请教原因
因为 post 过去的 body 实际上不是‘application/x-www-form-urlencoded’而是 json 字符串
response = requests.post(testUrl, headers=headers, data=json.dumps(submit_data))
我最近也遇到过类似问题。requests.post()抓汇率数据失败通常有几个常见原因:
- 请求头缺失:很多汇率网站需要完整的headers,特别是User-Agent和Referer
- 参数格式问题:POST参数可能需要form-data或json格式
- 需要会话维持:有些网站需要先获取cookies
给你个完整示例,我用这个成功抓过XE汇率数据:
import requests
import json
def fetch_exchange_rate():
url = "https://www.xe.com/api/protected/statistics"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'application/json',
'Accept-Language': 'en-US,en;q=0.9',
'Referer': 'https://www.xe.com/currencyconverter/',
'Content-Type': 'application/json'
}
# 先获取必要的cookies
session = requests.Session()
session.get('https://www.xe.com/currencyconverter/', headers=headers)
# POST请求参数(不同网站参数不同,需要分析)
payload = {
'from': 'USD',
'to': 'CNY',
'amount': 1
}
try:
response = session.post(url, headers=headers, json=payload, timeout=10)
response.raise_for_status()
# 检查响应内容
print(f"状态码: {response.status_code}")
print(f"响应头: {dict(response.headers)}")
if response.text:
data = response.json()
print(f"汇率数据: {data}")
return data
else:
print("响应内容为空")
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
except json.JSONDecodeError:
print(f"响应不是JSON格式: {response.text[:200]}")
if __name__ == "__main__":
fetch_exchange_rate()
调试建议:
- 先用浏览器开发者工具看实际的请求参数
- 打印response.status_code和response.text看具体错误
- 有些网站需要特定的Content-Type
关键点:先分析目标网站的实际请求,用session保持状态,确保headers完整。
一句话总结:检查请求头、参数格式和会话状态。
楼上说的比较明白了
然后那个 requests 的参数 data 可以直接用 json=
平时我处理这种请求, 基本上先复制请求的 CurlString, 然后 curlparse 出来, 必要时候 clean requestpython<br>from torequests.utils import curlparse<br>import requests<br><br>requests_args = curlparse(r'''curl '<a target="_blank" href="http://quote1.fx168.com/jrj/CurrencyConvert/ajaxpro/CurrencyConvert.ConvertJrj,jrj.ashx'" rel="nofollow noopener">http://quote1.fx168.com/jrj/CurrencyConvert/ajaxpro/CurrencyConvert.ConvertJrj,jrj.ashx'</a> -H 'Origin: <a target="_blank" href="http://quote1.fx168.com" rel="nofollow noopener">http://quote1.fx168.com</a>' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: zh-CN,zh;q=0.9' -H 'Ajax-method: Calculate' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: */*' -H 'Referer: <a target="_blank" href="http://quote1.fx168.com/Jrj/CurrencyConvert/ConvertJrj3.aspx'" rel="nofollow noopener">http://quote1.fx168.com/Jrj/CurrencyConvert/ConvertJrj3.aspx'</a> -H 'Connection: keep-alive' -H 'DNT: 1' --data $'{"moneys": "100", "start": "美元", "end": "人民币"}\r\n' --compressed --insecure''')<br>print(requests_args)<br># {'url': '<a target="_blank" href="http://quote1.fx168.com/jrj/CurrencyConvert/ajaxpro/CurrencyConvert.ConvertJrj,jrj.ashx'" rel="nofollow noopener">http://quote1.fx168.com/jrj/CurrencyConvert/ajaxpro/CurrencyConvert.ConvertJrj,jrj.ashx'</a>, 'headers': {'Origin': '<a target="_blank" href="http://quote1.fx168.com" rel="nofollow noopener">http://quote1.fx168.com</a>', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Ajax-Method': 'Calculate', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*', 'Referer': '<a target="_blank" href="http://quote1.fx168.com/Jrj/CurrencyConvert/ConvertJrj3.aspx'" rel="nofollow noopener">http://quote1.fx168.com/Jrj/CurrencyConvert/ConvertJrj3.aspx'</a>, 'Connection': 'keep-alive', 'Dnt': '1'}, 'data': b'{"moneys": "100", "start": "\xe7\xbe\x8e\xe5\x85\x83", "end": "\xe4\xba\xba\xe6\xb0\x91\xe5\xb8\x81"}\\r\\n', 'method': 'post'}<br>r = requests.request(**requests_args)<br>print(r.text)<br># "665.14"<br><br><br>
我修改之后获取到的数据是 1.91, 而不是 6.65, 这个问题在哪?
大概是美元和人民币几个汉字的编码问题,我也不清楚到底应该是什么编码,你可以从 2 楼的那个 requests_args 里面直接复制出来然后单纯修改 moneys 来用
获取结果是成功的谢谢, 我研究下。
为什么你不用 requests 解决呢?
#5 是因为网站就是这么干的,至于他们为什么要这么干我们就不知道了……
我的意思是用 curlparse 的你这种写法优视在哪?
谢谢
#10 刚发现这个请求体不是标准的 json- -
这么写就成功了
response = requests.post(
testUrl,
headers=headers,
data=’{“moneys”: “1”, “start”: “美元”, “end”: “人民币”}’.encode()
)
没弄明白这个网站是怎么构造出这个请求体的,直接拼接字符串么
‘{“moneys”: “1”, “start”: “美元”, “end”: “人民币”}’.encode(‘utf-8’)
curlparse 这种操作好有点骚啊,原来还可以这样玩
没啥操作啊… 就是把 CurlString 转 dict, 因为平时老是遇到漏填的参数, 后来直接全带上算了
后来自己也写出来了个 clean request 的, 就是把非必要参数过滤掉, 也就可以用最简参数发请求
他们用的是正经 json, 可能是你用法不对, 带中文部分不能直接 encode, 要么 json.dumps 把非 ascii 的转 unicode, 要么直接用 json= 参数, 放个 dict
你直接 encode 不一定对方要什么编码, 所以 json 库才有个 ensure_ascii 参数
你说的明明指定 form 却传 json, 可以看看 requests 源码, 发到服务器的时候, 就算 form dict 也会转成 bytes 的
莫名三连了… 已回复的没法 append 或者 edit 真淡腾…


