爬虫使用 requests post 抓取汇率失败, 请教原因. - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
woshichuanqilz
V2EX    Python

爬虫使用 requests post 抓取汇率失败, 请教原因.

  •  
  •   woshichuanqilz 2019-10-02 21:14:34 +08:00 5383 次点击
    这是一个创建于 2200 天前的主题,其中的信息可能已经有所发展或是发生改变。

    想从这个网站上获取人民币对美元的汇率, 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"'

    不知道我的代码问题在哪里, 请教一下。

    20 条回复    2019-10-03 14:34:00 +08:00
    Trim21
        1
    Trim21  
       2019-10-02 21:20:58 +08:00
    因为 post 过去的 body 实际上不是‘application/x-www-form-urlencoded’而是 json 字符串

    respOnse= requests.post(testUrl, headers=headers, data=json.dumps(submit_data))
    ClericPy
        2
    ClericPy  
       2019-10-02 21:35:28 +08:00   2
    楼上说的比较明白了
    然后那个 requests 的参数 data 可以直接用 json=

    平时我处理这种请求, 基本上先复制请求的 CurlString, 然后 curlparse 出来, 必要时候 clean request

    ```python
    from torequests.utils import curlparse
    import requests

    requests_args = curlparse(r'''curl 'http://quote1.fx168.com/jrj/CurrencyConvert/ajaxpro/CurrencyConvert.ConvertJrj,jrj.ashx' -H 'Origin: http://quote1.fx168.com' -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: http://quote1.fx168.com/Jrj/CurrencyConvert/ConvertJrj3.aspx' -H 'Connection: keep-alive' -H 'DNT: 1' --data $'{"moneys": "100", "start": "美元", "end": "人民币"}\r\n' --compressed --insecure''')
    print(requests_args)
    # {'url': 'http://quote1.fx168.com/jrj/CurrencyConvert/ajaxpro/CurrencyConvert.ConvertJrj,jrj.ashx', 'headers': {'Origin': 'http://quote1.fx168.com', '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': 'http://quote1.fx168.com/Jrj/CurrencyConvert/ConvertJrj3.aspx', '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'}
    r = requests.request(**requests_args)
    print(r.text)
    # "665.14"


    ```
    ClericPy
        3
    ClericPy  
       2019-10-02 21:35:47 +08:00
    这见鬼的排版... 想删帖都...
    woshichuanqilz
        4
    woshichuanqilz  
    OP
       2019-10-02 22:29:01 +08:00
    @Trim21 我修改之后获取到的数据是 1.91, 而不是 6.65, 这个问题在哪?
    woshichuanqilz
        5
    woshichuanqilz  
    OP
       2019-10-02 22:37:49 +08:00
    @Trim21 还有就是为什么 指定的是 application/x-www-form-urlencoded 传过去的确实 json 的数据呢?
    Trim21
        6
    Trim21  
       2019-10-02 22:38:17 +08:00
    @woshichuanqilz 大概是美元和人民币几个汉字的编码问题,我也不清楚到底应该是什么编码,你可以从 2 楼的那个 requests_args 里面直接复制出来然后单纯修改 moneys 来用
    woshichuanqilz
        7
    woshichuanqilz  
    OP
       2019-10-02 22:38:18 +08:00
    @ClericPy 获取结果是成功的谢谢, 我研究下。
    为什么你不用 requests 解决呢?
    Trim21
        8
    Trim21  
       2019-10-02 22:40:29 +08:00   1
    @woshichuanqilz #5 是因为网站就是这么干的,至于他们为什么要这么干我们就不知道了……
    woshichuanqilz
        9
    woshichuanqilz  
    OP
       2019-10-02 22:41:42 +08:00
    @ClericPy 我的意思是用 curlparse 的你这种写法优视在哪?
    woshichuanqilz
        10
    woshichuanqilz  
    OP
       2019-10-02 22:41:55 +08:00
    @Trim21 谢谢
    Trim21
        11
    Trim21  
       2019-10-02 23:28:50 +08:00
    @woshichuanqilz #10 刚发现这个请求体不是标准的 json- -
    这么写就成功了
    respOnse= requests.post(
    testUrl,
    headers=headers,
    data='{"moneys": "1", "start": "美元", "end": "人民币"}'.encode()
    )
    Trim21
        12
    Trim21  
       2019-10-02 23:40:24 +08:00
    没弄明白这个网站是怎么构造出这个请求体的,直接拼接字符串么
    ClericPy
        13
    ClericPy  
       2019-10-03 09:31:15 +08:00
    @woshichuanqilz 仔细看看那不就是用的 requests 库吗
    我之所以用 curlparse, 还不是让你看看它的原始请求体是什么, 解析成 requests 库可以用的 dict, 那就是最完整的请求
    203x
        14
    203x  
       2019-10-03 10:35:03 +08:00 via iPhone   1
    可以使用 汇率查询的免费 api
    https://fixer.io/
    snoopygao
        15
    snoopygao  
       2019-10-03 12:48:07 +08:00
    '{"moneys": "1", "start": "美元", "end": "人民币"}'.encode('utf-8')
    Hopetree
        16
    Hopetree  
       2019-10-03 13:45:34 +08:00
    @ClericPy curlparse 这种操作好有点骚啊,原来还可以这样玩
    TangMonk
        17
    TangMonk  
       2019-10-03 14:11:16 +08:00 via iPhone
    搞外汇?
    ClericPy
        18
    ClericPy  
       2019-10-03 14:29:43 +08:00
    @Hopetree 没啥操作啊.. 就是把 CurlString 转 dict, 因为平时老是遇到漏填的参数, 后来直接全带上算了
    后来自己也写出来了个 clean request 的, 就是把非必要参数过滤掉, 也就可以用最简参数发请求
    ClericPy
        19
    ClericPy  
       2019-10-03 14:32:22 +08:00
    @Trim21 他们用的是正经 json, 可能是你用法不对, 带中文部分不能直接 encode, 要么 json.dumps 把非 ascii 的转 unicode, 要么直接用 json= 参数, 放个 dict
    你直接 encode 不一定对方要什么编码, 所以 json 库才有个 ensure_ascii 参数
    ClericPy
        20
    ClericPy  
       2019-10-03 14:34:00 +08:00
    @woshichuanqilz 你说的明明指定 form 却传 json, 可以看看 requests 源码, 发到服务器的时候, 就算 form dict 也会转成 bytes 的


    莫名三连了... 已回复的没法 append 或者 edit 真淡腾...
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2957 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 13:35 PVG 21:35 LAX 06:35 JFK 09:35
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86