求助:利用 requests 模拟登录,中文数据提交 + 两次 302 重定向 - 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
zvDC
V2EX    Python

求助:利用 requests 模拟登录,中文数据提交 + 两次 302 重定向

  •  
  •   zvDC 2015-01-17 23:31:07 +08:00 15181 次点击
    这是一个创建于 3921 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,想利用python的requests来进行网站的模拟登录,苦于技术太差,纠结了许久,也到处搜索还是没有找到答案,烦请大家帮忙。

    问题是:
    1、如何处理form data中提交的数据为中文的编码问题?
    2、如何处理两次302,"object moved"重定向的问题,在requests中如何写代码?

    这是成功登录时的抓包图:
    wireshark
    http://i.imgur.com/Z1qcWH7.png
    Chrome DevTools
    http://i.imgur.com/YkEuq1s.png

    有问题的代码如下:

    import requests

    url_login = 'http://www.example.com/RedeployCourse/login.asp'
    url_default = 'http://www.example.com/RedeployCourse/default.asp'
    url_info = 'http://www.example.com/RedeployCourse/RedeployInfo.asp'

    headers = { 'Content-Type': 'application/x-www-form-urlencoded',}
    form_data={"username": '中文用户名',"password":'abcdef'}

    s = requests.Session()
    s.get(url_login)

    r = s.post(url_login, data=form_data, headers=headers, allow_redirects=False)

    s.get(url_default)
    r = s.get(url_info)

    16 条回复    2015-01-23 05:27:23 +08:00
    14
        1
    14  
       2015-01-17 23:41:59 +08:00   1
    In [1]: import urllib

    In [2]: urllib.quote('中文用户名')
    Out[2]: '%E4%B8%AD%E6%96%87%E7%94%A8%E6%88%B7%E5%90%8D'

    第二个没明白你的意思,这个可能对你有帮助: http://stackoverflow.com/questions/20475552/python-requests-library-redirect-new-url
    aaaa007cn
        2
    aaaa007cn  
       2015-01-18 01:02:07 +08:00   1
    302 有什么问题?
    已经事先知道目标网址的话
    最多就是再带上 cookie 和 referer
    cookie 已经由 session 处理了
    referer 看场合也有不需要的
    s.get(url_default, allow_redirects=False, headers={"referer": url_login})
    r = s.get(url_info, allow_redirects=False, headers={"referer": url_default})
    不知道目标网址的话就从 r.headers["Location"] 来取跳转的网址

    不过 requests 默认 allow_redirects 为 True 的
    也可以让它自动跳转
    ericFork
        3
    ericFork  
       2015-01-18 06:11:59 +08:00   1
    如果不是非要用 Python 的话,可以试试 casperjs
    zvDC
        4
    zvDC  
    OP
       2015-01-18 08:22:36 +08:00
    @14 @aaaa007cn @zvDC 谢谢各位的回复

    我想还是先把第一个问题解决吧

    服务端页面编码为 <meta http-equiv="Content-Type" cOntent="text/html; charset=">
    提交中文的问题,我还有疑问:
    拿 “登录”二字举例,

    unicode 字符
    In [1]: u"登录"
    Out[1]: u'\u767b\u5f55'

    转换成格式
    In [2]: u'登录'.encode(' ')
    Out[2]: '\xb5\xc7\xc2\xbc'

    进行URL编码
    In [3]: urllib.quote(u'登录'.encode(''))
    Out[3]: '%B5%C7%C2%BC'

    这样转换成编码之后,与cookie中对应的字符显示是一致的
    可是通过wireshark抓包,却发现,正确的值应该是:\265\307\302\274
    请问这是如何实现的,或者哪个地方我忽略了,谢谢!
    zvDC
        5
    zvDC  
    OP
       2015-01-18 08:31:51 +08:00
    @aaaa007cn 你好
    使用
    s = requests.session()
    这个应该是可以把cookies一直保留,直到会话结束。
    在这种情况下:
    1、是否,只要我post过去的值是正确的,就不需要再添加新的值?
      (因为,我发现用脚本post比真实提交的cookie值少了一些)

    2、如果需要添加,如何向cookies中添加新的值,比如{"name":'value'}?
    zvDC
        6
    zvDC  
    OP
       2015-01-18 10:48:20 +08:00
    在  http://www.v2ex.com/t/97347 中看到修改cookie值的方法

    def update_cookie(cookiejar, cookie):
    _cookies = requests.cookies
    _cookies.remove_cookie_by_name(cookiejar, 'cookie_name')
    cookiejar.set_cookie(_cookies.create_cookie('cookie_name', cookie, **{'domain': '.example.com'}))
    ming2050
        7
    ming2050  
       2015-01-18 11:14:53 +08:00 via Android   1
    redirect这个属性为true就没多大问题吧
    Sylv
        8
    Sylv  
       2015-01-18 12:45:46 +08:00   1
    '\xb5\xc7\xc2\xbc' 和 '\265\307\302\274' 应该是等价的,只是表示方式不一样,不过是一个写成的是16进制,一个写成的是8进制的。所以应该直接提交 u'登录'.encode(' ') 就好了。

    根据 requests 文档,向 requests.Session 的 cookies 中添加新值,应该这样就好了:
    s.cookies.update({"name":'value'})

    另外我不理解为什么你在 r = s.post(url_login) 之前还要 s.get(url_login) 一次?同样的还有 s.get(url_default)?看样子你不需要这两个的 response,那为什么要多此一举地 get 一下呢?
    mengskysama
        9
    mengskysama  
       2015-01-18 14:39:34 +08:00   2
    楼主其实昨天我看了下,我没敢给你贴上来,这样真的好吗?

    登陆很简单,因为web后端吃的是所以中文必须要先编码成2312,然后再让他做urlencode,这个requests能自己帮你做好。你不用urllib.quote

    还有就是requests会自动做decode成unicode,如果返回的头部没有指定ISO-XXX什么的,这样.text获取到的就是错误的unicode r.encoding = ''


    url_login = 'http://os.ningboerji.com:82/RedeployCourse/login.asp'
    headers = { 'Content-Type': 'application/x-www-form-urlencoded'}
    form_data={"UserName": '\'or\' = \'or\'',"Pwd":'','B1':u'登录'.encode('')}
    s = requests.Session()
    r = s.post(url_login, data=form_data, headers=headers)
    r.encoding = ''
    print r.text.encode('utf-8')
    exit(1)
    zvDC
        10
    zvDC  
    OP
       2015-01-18 14:40:53 +08:00
    @mringg 谢谢回复,requests 默认 allow_redirects 为 True,没能成功。

    @Sylv 谢谢。如你所说,'\xb5\xc7\xc2\xbc' 和 '\265\307\302\274' 应该是等价的,没有想到。是否有方法指定要生成的进制模式。

    之所以在post之前,先 s.get(url_login) 一下的原因,是想获得一个session cookie的值,后边要用到。

    后边的s.get(url_default),是因为在F12或者抓包里看到的都是在这样一个地址……

    (对于上面的做法,我都不确定是否有用,刚刚开始学习,只是在尝试)
    mengskysama
        11
    mengskysama  
       2015-01-18 14:51:21 +08:00   1
    如果没猜错你的系统和上面的一样有注入漏洞,在登录'or' = 'or'试试?迟早被人捅
    zvDC
        12
    zvDC  
    OP
       2015-01-18 14:51:23 +08:00
    @mengskysama 太感谢了。谢谢你。
    “这样好吗?”,放心,不是做坏事。
    只是地址链接能否修改一下,不公开呀?

    v2不能发私信,也不知道你现在还可以修改吗?
    mengskysama
        13
    mengskysama  
       2015-01-18 15:11:38 +08:00   1
    @zvDC V2不能编辑也不能删除
    我看你的DEST IP 和这个不匹配我就贴了..本想给你做个完成的例子..并不是有意冒犯。
    如果你是管理员,还是赶紧补掉吧。
    zvDC
        14
    zvDC  
    OP
       2015-01-18 15:16:46 +08:00
    @mengskysama 没事,谢谢。
    我不是管理员,只是不想因为我给别人带来不必要的麻烦。
    关注你了,向你学习。
    aaaa007cn
        15
    aaaa007cn  
       2015-01-20 00:16:37 +08:00   1
    >> 是否,只要我post过去的值是正确的,就不需要再添加新的值?
    session 已经自动处理了 cookie
    一般不需要手动更新

    >> 因为,我发现用脚本post比真实提交的cookie值少了一些
    可能是你先前少请求了某些页面
    也可能是真实提交时多了一些
    建议清掉浏览器 cookie 或者新开隐身模式去测试

    >> requests 默认 allow_redirects 为 True,没能成功
    怎么不成功
    贴出相关信息
    比如出错信息
    比如 r.history
    比如 r.text
    zvDC
        16
    zvDC  
    OP
       2015-01-23 05:27:23 +08:00
    @aaaa007cn 谢谢!
    对隐身模式测试,以前不知道,下次可以试试。
    问题出在我对编码这块了解不清,这块问题解决了,后面就没有问题了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5876 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 03:21 PVG 11:21 LAX 20:21 JFK 23:21
    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