pylogin 系列之 V2EX 自动领币消息提醒 - 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
anhkgg
V2EX    Python

pylogin 系列之 V2EX 自动领币消息提醒

  •  
  •   anhkgg
    anhkgg 2017-08-18 21:30:47 +08:00 3322 次点击
    这是一个创建于 3046 天前的主题,其中的信息可能已经有所发展或是发生改变。

    概述

    最近开始混 v2ex,v2ex 发主题、回复都要收钱,发帖收钱还跟字数相关,之前不知道这些,发个帖子内容太多,kao,没钱了!

    虽然主题有人回复会收到钱,但是也没人回复啊,也不知道 V2EX 大佬们喜欢什么内容!

    幸好 V2EX 有个登录领币任务,每天还可以攒点钱,但是有些时候会忘啊,怎么办?...

    嗯,程序员嘛,偷懒的办法多...这就开始分析接口,自动领币!

    然后呢,发个主题,总想看看有没有大佬关注和回复,然后就时不时打开浏览器,去刷新一下页面。

    就跟大部分用 windows 的人一样,回到桌面不右键+E (刷新)一下,就感觉人生好像少了什么东西(我好像是重症患者,用 ubuntu 也要找一下刷新桌面)!

    这种情况是不是病啊?!

    然后呢,刷新很浪费时间诶,有人回复,看着还算开心嘛,但也没人回复,那不白浪费时间了嘛,还影响期待的小心情!

    所以呢,还得加上自动消息提醒功能!

    废话完毕,开始干活!

    工具:

    1. chrome/firefox 2. f12,network 3. python:requests、re 

    登录

    开始分析登录接口。打开 chrome,f12,进入登录页面。只需要输入名字和密码,没有验证码,真好!

    访问的链接是:

    signin 

    然后随便输入什么名字和密码,点击登录,肯定失败,页面有提示。再看网络请求数据:

    POST signin Host: www.v2ex.com User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:54.0) Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 //发送数据 6b79e5fdb638c190396648c486c313dca73ad9f6e4e122fafc356e54522eedc4:"111111111111111" //name bb4419eb55aef4106a853ce9f4642d5d58ac021f4e1fef29a230e2352da74802:"11111111111" //password once:"95083" next:"/" //登录错误 <div class="box"> <div class="header"><a href="/">V2EX</a> <span class="chevron">&nbsp;&nbsp;</span> 登录 &nbsp;<li class="fa fa-lock"></li></div> <div class="problem">请解决以下问题然后再提交:<ul><li>用户名和密码无法匹配</li></ul></div> ... </div> 

    这个请求关键点:

    1. POST 请求,url 是signin
    2. 发送数据有名字和明文密码,以及两个其他不明字段
    3. 请求是 https,所以明文密码不会暴露。

    在仔细看发送的 4 个数据。 名字和密码对应的字段都是一长串字符,猜想这个是变化的,每次刷新登录页面都不一样,多次尝试下确认该猜想!

    如何获取呢,肯定是在打开登录页面时就会收到服务器返回的这两个字符串的。在登录 html 内容中一翻,看到如下:

    <div class="box"> <div class="header"><a href="/">V2EX</a> <span class="chevron">&nbsp;&nbsp;</span> 登录 &nbsp;<li class="fa fa-lock"></li></div> <div class="cell"> <form method="post" action="/signin"> <table cellpadding="5" cellspacing="0" border="0" width="100%"> <tr> <td width="120" align="right">用户名</td> <td width="auto" align="left"><input type="text" class="sl" name="804c76d3f1472cdd8721d16f21de446186f2bae893748542ffda39963ff293f4" value="111111111111111" autofocus="autofocus" autocorrect="off" spellcheck="false" autocapitalize="off" placeholder="用户名或电子邮箱地址" /></td> </tr> <tr> <td width="120" align="right">密码</td> <td width="auto" align="left"><input type="password" class="sl" name="359a3968b3b6f37b05fceed766bd8995090a4fd5cdc74ba0a8cd17b44d2bc86e" value="" autocorrect="off" spellcheck="false" autocapitalize="off" /></td> </tr> <tr> <td width="120" align="right"></td> <td width="auto" align="left"><input type="hidden" value="79599" name="once" /><input type="submit" class="super normal button" value="登录" /></td> </tr> <tr> <td width="120" align="right"></td> <td width="auto" align="left"><a href="/forgot">我忘记密码了</a></td> </tr> </table> <input type="hidden" value="/" name="next" /> </form> </div> </div> 

    名字对应字段是<input type="text" class="sl" name="804c76d3f1472cdd8721d16f21de446186f2bae893748542ffda39963ff293f4"

    密码对应字段是<input type="password" class="sl" name="359a3968b3b6f37b05fceed766bd8995090a4fd5cdc74ba0a8cd17b44d2bc86e"

    可以通过正则获取到字段名。

    名字正则:r'<input type="text" class="sl" name="([\d\w]*?)"'

    密码正则:r'<input type="password" class="sl" name="([\d\w]*?)"'

    也看到了其他两个数据字段,<input type="hidden" value="79599" name="once" /><input type="hidden" value="/" name"next" />

    once对应的值每次都不一样,next的值应该是固定的/,但是为了保险,都通过正则来获取

    r'<input type="hidden" value="([\d\w]+?)" name="once" />' r'<input type="hidden" value="(.+?)" name="next" />' 

    好了,到此登录请求需要的东西都分析完了,然后就是模拟接口发送请求了。

    忘了还有一点,返回状态的判断。

    前面看到登录错误的有提示信息,为了更人性化,把这个信息拿到吧。

    //登录错误 <div class="box"> <div class="header"><a href="/">V2EX</a> <span class="chevron">&nbsp;&nbsp;</span> 登录 &nbsp;<li class="fa fa-lock"></li></div> <div class="problem">请解决以下问题然后再提交:<ul><li>用户名和密码无法匹配</li></ul></div> 

    获取错误信息正则是这样:r'<div class="problem">.+?<ul><li>(.*?)</li></ul></div>'

    登录成功判断待会儿再分析。

    通过 py 发送模拟登陆请求,代码如下:

    payload = { self.form_name:name, self.form_pass:pwd, 'once': self.form_once, 'next': self.form_next } r = self.s.post(url, data=payload, headers=headers) 

    保存了返回数据一看,没成功啊,还是未登录的首页。

    重新再浏览器登录一下,仔细分析了一下。

    发送了登录请求之后,登录成功之后,页面自动跳转到https://www.v2ex.com,有登录信息了。

    猜测对请求的头部数据做了某些校验。

    看看请求的头部数据,如下:

    Host: www.v2ex.com User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:54.0) ... Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate, br Content-Type: application/x-www-form-urlencoded Content-Length: 167 Referer: signin Connection: keep-alive Upgrade-Insecure-Requests: 1 

    一般来说可能会对 host,referer 等字段检查,加入尝试一下。

    headers = { #'Host': 'www.v2ex.com', #'origin':'https://www.v2ex.com', 'referer':'signin', } 

    成功登录,屏蔽其中一些字段,发现只需要加入 referer 即可登录。

    获取登录成功状态,可以看到登录成功后,会有用户账户信息,如下:

    <a href="/member/anhkgg" class="top">anhkgg</a>&nbsp;&nbsp;&nbsp; <a href="https://workspace.v2ex.com/" target="_blank" class="top">工作空间</a>&nbsp;&nbsp;&nbsp; <a href="/notes" class="top">记事本</a>&nbsp;&nbsp;&nbsp;<a href="/t" class="top">时间轴</a>&nbsp;&nbsp;&nbsp;<a href="/settings" class="top">设置</a>&nbsp;&nbsp;&nbsp; <a href="#;" Onclick="if (confirm('确定要从 V2EX 登出?')) { location.href= '/signout?Once=54090'; }" class="top">登出</a></td> 

    那么只需要搜索是否存在<a href="/member/anhkgg"即可。正则表达式是:r'<a href="/member/.+?">'。找到该内容表示登录成功。

    退出

    登录成功了,顺便看一下退出的接口。抓包看一下,发现访问了如下链接:

    signout?Once=71351 

    又见到 once 字段,值又是每次不同的。那么也只有动态获取一下了。在前面登录成功的信息中其实可以看到有退出接口的内容。

     Onclick="if (confirm('确定要从 V2EX 登出?')) { location.href= '/signout?Once=54090'; }" class="top">登出</a></td> 

    通过正则获取一下 once:r"location.href= '/signout\?Once=([\d\w]+?)'",然后模拟退出。

    url = 'signout' payload = { 'once': self.signout_once} self.s.get(url, params=payload) 

    新评论

    接着就看看我需要的功能了。

    首先是获取最新评论条数。找到对应 html 的内容,如下:

    </a></div><a href="/notifications" class="fade">0 条未读提醒</a></div> 

    非常简单,关键字 notifications,正则一搜即可拿到。

    r'</div><a href="/notifications" class="fade">(\d+?)(.*?)</a>'

    不在细说。

    为了能主动提醒我是否有最新消息,登录成功后,没 10 分钟刷新一下https://www.v2ex.com,再获取评论条数即可。

    有新评论就通知我。

    领取每日奖励

    嗯,钱的事还是挺重要的。

    首页右侧,每天会出现领取今日奖励的按钮,什么时候出现不知道(过了凌晨 12 点?),点击后跳转到领取页面,再点击领取按钮就拿到钱了!

    第一步,拿到领取页面的链接。看下面,是固定的,终于省了一点点事。

    <div class="box"><div class="inner"><li class="fa fa-gift" style="color: #f90;"></li> &nbsp;<a href="/mission/daily">领取今日的登录奖励</a></div></div> 

    通过下面的代码跳到领取页面。

    url = 'mission/daily' r= self.s.get(url) 

    然后看看领取按钮对应的链接,又见 once ! so,链接不是固定的了。

    <div class="cell"> <h1>每日登录奖励 20170818</h1> <input type="button" class="super normal button" value="领取 X 铜币" Onclick="location.href = '/mission/daily/redeem?Once=48881';" /> </div> 

    动态获取 once 对应的值,正则跟退出接口很像:r"'/mission/daily/redeem\?Once=([\d\w]+?)'"

    然后模拟请求领取奖励。

    url = 'mission/daily/redeem' payload = { 'once': once} r = self.s.get(url, params=payload) 

    总结

    好了,到这里分析就完成了。分析内容非常详细,然后也贴了些关键代码,所以完整代码就暂时不提供了!

    v2ex 登录通过变化的名字和密码字段,以及 once 的值,增加了一定的分析成本,但是总的来说,还是没什么难度!挡不了多少人!

    其他自动回复啊,最新主题啊...等等,各位看官自行脑洞了!

    pylogin 系列还将继续,尽请关注!

    博客原文:https://anhkgg.github.io/pylogin-v2ex-login-analyze/

    4 条回复    2017-08-19 04:30:17 +08:00
    Yourshell
        1
    Yourshell  
       2017-08-18 22:33:09 +08:00
    对菜鸡很友好哈
    eoo
        2
    eoo  
       2017-08-18 22:47:43 +08:00 via Android/span>
    我只能说一点难度都没有。。。。。
    hzwei
        3
    hzwei  
       2017-08-19 00:09:39 +08:00 via Android
    你写代码注释时也喜欢在每句话后面加个“!”吗?
    ysc3839
        4
    ysc3839  
       2017-08-19 04:30:17 +08:00 via Android
    我似乎有一次遇到了点领取奖励,让你再点一次才能领取的情况,提醒你一下。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2595 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 07:14 PVG 15:14 LAX 23:14 JFK 02:14
    Do have faith in what you're doing.
    ubao msn 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