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
Huayx9
V2EX  ›  Python

模拟登陆中 302 重定向和 cookies 的一些困惑

  •  
  •   Huayx9 · 2016-07-31 21:32:29 +08:00 · 11537 次点击
    这是一个创建于 3068 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我想写一个查询话费和流量的爬虫,关键是实现模拟登陆的这个部分。 在登陆过程中,点击登陆之后,登陆表单会 post 到一个地址(这一步浏览器不显示),然后会 302 跳转到登陆成功的页面。

    我现在想得到登陆成功的 cookies ,不知道该怎么提取,requests.session()并没有得到登陆成功的 cookies. 得不到登陆成功的 cookies ,代码就不能爬取登陆之后的查询信息。

    post 表单的地址 http://i.imgur.com/2OS1Zi1.png

    登陆过程中的重定向 1 http://i.imgur.com/cI6wBCV.png

    登陆过程中的重定向 2 http://i.imgur.com/3c19Y38.png

    再跳转登陆成功的页面 http://i.imgur.com/uAZsUdI.png

    我有三个问题

    • 1.post 表单这个过程,也就是图一中的 cookies 是怎么生成的,因为我发现 post 表单过程中的 cookies 比在进入登陆页面中的多。
    • 2.登陆过程中有两次 302 ,最后再 200 到登陆成功页面,我该怎么得到 200 的这个 cookie 。
    • 3.request.sission()是会自动管理登陆过程中的 cookies 吗,用不用单独提取登陆之后的 cookies 。

    代码如下,谢谢大家

    #coding=utf-8
    import requests
    import re
    
    # request headers
    Head ={'Accept-Language': 'zh-CN,zh;q=0.8', 'Accept-Encoding': 'gzip, deflate, sdch', 'Host': 'ah.189.cn',
           'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Upgrade-Insecure-Requests': '1', 'Connection': 'keep-alive', 'Cache-Control': 'max-age=0',
           'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36'}
    
    
    # Chrome 打开登陆页面提取的 cookies
    Cook = {'Hm_lvt_333c7327dca1d300fd7235c159b7da04': '1469964315',
            'lid': '', '_gscu_1758414200': '69964315ee6pb621', 'v_lasttime': '1469964315502',
            '_gscs_1758414200': '69964315tq317521|pv:1', 'Hm_lvt_c7c8eed8670bd7fffefc8b202fe0904d': '1469964315',
            'v_url_code': 'http%3A//ah.189.cn/sso/login%3FreturnUrl%3D%252Fbiz%252Fservice%252Faccount%252Finit.action',
            'JSESSIONID_SSO': 'Jh1GXdgDZJqdZqpLvRQvZzdlvT7y6BxHhCny9MhbKh1Kw1hSLNt2Q1c6231LrHQWrpDL4m115pz0YTLJN7jx2fmpTfPBx1JwlYvvkLBRySmy18tnW1c2Q7qPvQqK9kJP!463350529',
            'v_trackId': '1BD7B46E79FE234CE9C67E49D95245FB', 'Hm_lpvt_333c7327dca1d300fd7235c159b7da04': '1469964315',
            '_gscbrs_1758414200': '1', 'Hm_lpvt_c7c8eed8670bd7fffefc8b202fe0904d': '1469964315',
            'JSESSIONID_PERSONWEB': 'p2MyXdgGd8f5phjTTv2CJMr6J8QYhSyLX0kkZHlSwpppjhYGf3qm!1538637772'}
    
    #登陆提交的表单
    postdata = {'remPwd': '0',
            'loginName': '',
            'returnUrl': '/biz/service/account/init.action',
            'validCode': '',
            'loginType': '4', 'sysId': '1003', 'passType': '0',
            'csrftoken': '',
            'accountType': '9', 'ssoAuth': '0',
            'passWord': '',
            'latnId': '551'}
    
    
    #登陆页面
    baseurl = 'http://ah.189.cn/sso/login?returnUrl=%2Fbiz%2Fservice%2Faccount%2Finit.action'
    #登陆表单 post 的地址
    posturl = 'http://ah.189.cn/sso/LoginServlet'
    
    
    
    sess = requests.session()
    sess.headers.update(Head)
    
    def getP(url,cookies):
        """带 session()requests 的 get 方法"""
        pre = sess.get(url,cookies = cookies)
        return pre
    
    def getVerifyURL(url):
        """从主页提取验证码地址"""
        reg = r'/sso/VImage.servlet\?random=0\.[0-9]+'      #正则表达式匹配验证码图片链接
        img = re.search(reg,getP(url,cookies = Cook).content).group()
        imge = "http://ah.189.cn" + img     #得到验证码图片链接
        return imge
    
    def getCodePic():
        """下载验证码图片"""
        verifyURL = getVerifyURL(baseurl)
        codePic = getP(verifyURL,cookies = Cook).content
        print verifyURL
        with open('x.jpeg','wb') as jpg:
            jpg.write(codePic)
    
    def postData():
        """post 表单信息更新"""
        username = raw_input("输入手机号")
        code = raw_input("输入密码")
        passwd = raw_input("输入验证码")
        postdata['loginName'] = str(username)
        postdata['validCode'] = str(code)
        postdata['passWord'] = str(passwd)
    
    getCodePic()
    postData()
    
    postover = sess.post(posturl,postdata)       #post 表单
    cookLogin = postover.cookies       #查看 post 表单之后的 cookies
    print cookLogin
    con = sess.get('http://ah.189.cn/biz/service/account/init.action')
    #登陆成功的页面
    print "登陆成功",con
    
    
    29 条回复    2017-12-05 16:10:44 +08:00
    Huayx9
        1
    Huayx9  
    OP
       2016-07-31 21:33:05 +08:00
    图片显示不成功好像。。。。
    iluhcm
        2
    iluhcm  
       2016-07-31 22:24:41 +08:00   ❤️ 1
    遇到类似问题,表示关注。。
    lxy
        3
    lxy  
       2016-07-31 22:56:45 +08:00   ❤️ 1
    懒得具体分析了,简单说下经验。
    1 、 cookies 在任何时候都能够被设置。如果是我来做这个,我会先获取( get )登录的页面(大多数时候会在这里设置 cookies 和 token ),模拟人工操作,而不是一开始就提交( post )数据。顺便注意 JS 也可以设置 cookies 。
    2 、 requests 会自动处理 cookies 和 302 。
    3 、同上。不过好像 requests 有个坑,不知道是不是因为自己项目中对 requests 封装过度导致的,在访问多个不同的子域名的时候,貌似会混淆*同名的*cookies ,需要手动指定 cookies 。可以注意一下。
    scnace
        4
    scnace  
       2016-07-31 22:59:18 +08:00 via Android   ❤️ 1
    我之前爬学校也遇到过 302 Object moved here 的问题 要 header 里面设置下 Referer 你可以试试(
    digihero
        5
    digihero  
       2016-07-31 23:01:22 +08:00   ❤️ 1
    python 不了解。不过用 PHP 来模拟的时候,碰到 302 ,是可以设置 CURL 的参数来实现跟踪跳转的。到跳那儿就跟到那儿。 python 一样可以,看看参数。
    aeshfawre
        6
    aeshfawre  
       2016-07-31 23:04:43 +08:00   ❤️ 1
    你这三个问题等于一个问题,就是 cookie. 用了 Session(),你就不需要管任何 cookie 的问题了.

    问个问题,你这是做出来自用的么,还是拿出去卖的,python 代码写出来的会被倒卖吧.静态编译的才适合出售.
    Huayx9
        7
    Huayx9  
    OP
       2016-07-31 23:07:58 +08:00
    @aeshfawre 我是做出来自用的。。还是学生,写的这么蹩脚
    Huayx9
        8
    Huayx9  
    OP
       2016-07-31 23:12:39 +08:00
    @lxy 我是先 get 登陆页面, get 验证码,然后再 post 表单,用了 session()不是会自动管理 cookies 么, post 之后的 cookies 不是自动更新么。难道是 post 之后再 get 混淆类 cookies 了?在 post 之后获取 cookies 参数,再指定给( get 登陆成功页面)这个操作?
    Huayx9
        9
    Huayx9  
    OP
       2016-07-31 23:14:04 +08:00
    @scnace 是每一步都要设置 referer 吗,那岂不是每一个 requests 的 headers 都不同了?
    Huayx9
        10
    Huayx9  
    OP
       2016-07-31 23:14:48 +08:00
    @digihero 谢谢啦,那么现在的主要问题是,怎么得到登陆成功的 cookies 。。
    aeshfawre
        11
    aeshfawre  
       2016-07-31 23:17:18 +08:00   ❤️ 1
    @Huayx9 学生怎么会有这需求,以前是养卡或者开移动营业厅的人买我软件,我人生最大的遗憾就是没去了解自己处于这个食物链的哪一层.

    现在都还不明白这软件具体有啥用途,你能告诉我不?
    Huayx9
        12
    Huayx9  
    OP
       2016-07-31 23:29:01 +08:00
    @aeshfawre 我哥哥让我做一个软件,帮他批量查询他的电信号的余额和消费情况,他开公司的。

    然后,我就想到用爬虫来做,难不成我还能是盗卡的么,就我这破水平。。
    Huayx9
        13
    Huayx9  
    OP
       2016-07-31 23:35:14 +08:00
    @aeshfawre 还有,我做的过程中,巩固 python 水平,掌握基础的写爬虫技能,熟悉 http 协议,如果写好了,我哥给我一点好处那更好不过了。。

    我现在一直就是模拟登陆不成功, post 表单之后就抓瞎了。。。 cookies 总是不正常,也就 get 不到登陆成功的页面的信息。

    谢谢你一直的耐心解答。。 cookies 这一关我过不了啊。。
    scnace
        14
    scnace  
       2016-08-01 07:36:34 +08:00 via Android
    @Huayx9 额 碰到 302 了再 referer 啊 network 里应该有写吧 我在 blog 里写过的 你可以参考下 差不多场景 http://scnace.cc/wordpress/archives/1117
    jackyspy
        15
    jackyspy  
       2016-08-01 08:12:54 +08:00
    @Huayx9 你这个需求, selenium2 也是一个不错的选择
    Huayx9
        16
    Huayx9  
    OP
       2016-08-01 08:23:14 +08:00 via iPhone
    @jackyspy 验证码我准备假如一个 OCR 模块, selenium2 能够拓展么?
    Huayx9
        17
    Huayx9  
    OP
       2016-08-01 08:24:15 +08:00 via iPhone
    @scnace 咿呀,加个什么其他好友吧,有机会交流学习~
    scnace
        18
    scnace  
       2016-08-01 08:31:26 +08:00 via Android
    @Huayx9 wechat:c2NiaXp1Cg==
    Huayx9
        19
    Huayx9  
    OP
       2016-08-01 08:37:32 +08:00 via iPhone
    @scnace 有没有等号。。
    scnace
        20
    scnace  
       2016-08-01 08:54:16 +08:00 via Android
    @Huayx9 我稍微 base64 加了下密 你去 decode 一下 就行了😂
    Huayx9
        21
    Huayx9  
    OP
       2016-08-01 09:06:38 +08:00 via iPhone
    @scnace 等号。。有的没的
    lslqtz
        22
    lslqtz  
       2016-08-01 09:47:28 +08:00
    @scnace 话说 wechat 为啥要 base64 不是只有邮件防爬虫 base64 么。。
    jackyspy
        23
    jackyspy  
       2016-08-01 09:55:06 +08:00
    @Huayx9 selenium2 只是操控浏览器
    Huayx9
        24
    Huayx9  
    OP
       2016-08-01 10:43:33 +08:00 via iPhone   ❤️ 1
    @lslqtz 太直接了,也容易暴露
    HFcbyqP0iVO5KM05
        25
    HFcbyqP0iVO5KM05  
       2016-08-01 18:53:14 +08:00 via Android
    我只是提醒一下,题主你试过 allow_redirects=True 了吗?
    HFcbyqP0iVO5KM05
        26
    HFcbyqP0iVO5KM05  
       2016-08-01 18:58:02 +08:00 via Android
    @lxy 你说的 cookie 同名应该是同样的 name=value pair 吧。 严格来说 cookie 更像一个 OrderedDict , 里面的 name=value 相同,但其它的什么 path, hosts, expire 信息不同的话算两个 cookie 。
    coolloves
        27
    coolloves  
       2016-08-01 23:11:36 +08:00 via iPhone
    mark
    lxy
        28
    lxy  
       2016-08-04 10:51:41 +08:00
    @Huayx9 抽空检查了一下项目代码,是我自己的问题…… 某处调用了 requests.cookies.get_dict() 未指定域名且返回的信息不包括域名信息,进而导致了同名 cookies 混淆……
    shanechiu
        29
    shanechiu  
       2017-12-05 16:10:44 +08:00
    一个很好的问题。的确,会经常碰到临时重定向的情况。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5818 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 02:50 · PVG 10:50 · LAX 18:50 · JFK 21:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.