edfward

与虾米签到奋斗的日子

室友再三怂恿说做一个自动签到的东西吧,整天提心吊胆担心忘记签到的日子实在是太憋屈了,用网上的插件又担心账号的安全问题。于是今天早晨开始兴致盎然的研究起怎么做这件事情。

首先看到的是一段 php 代码。仿照这个逻辑直接写 curl:

curl -c ./cookie.txt \
    --referer 'http://www.xiami.com/web/login' \
    -A 'Opera/9.60' \
    -d "email=$email&password=$password&LoginButton=登陆" \
    http://www.xiami.com/web/login

-c cookie-jar 来保存cookies到文件,--referer 表明访问请求来自之后的那个 url,-A 是 user-agent,-d 提交 POST 数据(当然记得准备好 email 和 password)。之后进入虾米的手机版页面就能顺利拿到 cookies 啦。(登陆实际上就是填一个表单然后 POST 过去,所以只要知道 POST 数据的格式事情就会很简单。那个 LoginButton 比较麻烦。)

curl --cookie ./cookie.txt http://www.xiami.com/web > page.txt

用这份 cookie 抓下网页,再用 sed 去匹配看能不能找到签到的地址,然后按网上的说法只要对着那个地址 POST 一个空的东西就行了。

curl --cookie ./cookie.txt \
    -e http://www.xiami.com/web \
    -A 'Opera/9.99' \
    -X POST http://www.xiami.com/web/checkin/id/13906799

逻辑与上面一样,指定了 -X POST 方法,但始终不管用。多方查探无果后只好转向 python 的怀抱

import urllib2
import urllib
import cookielib
import re

users = []; # DIY!

cj = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
urllib2.install_opener(opener)
# 让urllib2.Request拿下cookies

login_url = 'http://www.xiami.com/web/login'
login_headers = {'Referer':'http://www.xiami.com/web/login', 'User-Agent':'Opera/9.60',}
checkin_headers = {'Referer':'http://www.xiami.com/web', 'User-Agent':'Opera/9.99',}
checkin_pattern = re.compile(r'<a class="check_in" href="(.*?)">')
# 事先决定好 header,url之类

for user in users:
    login_data = urllib.urlencode({'email':user[0], 
        'password':user[1], 'LoginButton':'\xe7\x99\xbb\xe9\x99\x86',})            
    login_request = urllib2.Request(login_url, login_data, login_headers) 
    login_response = urllib2.urlopen(login_request).read()
    checkin_result = checkin_pattern.search(login_response)
    if not checkin_result: 
        print user[0],' fails'
        continue
    checkin_url = 'http://www.xiami.com' + checkin_result.group(1)  
    checkin_request = urllib2.Request(checkin_url, None, checkin_headers)
    checkin_response = urllib2.urlopen(checkin_request)
    cj.clear()
    print checkin_response.geturl() 

urllib2、urllib 和 re 的文档都还算清晰明朗。

可以看到最后的 checkin_request 的第二个 data 参数为 None,不知道在 curl 里能不能做到一样的效果。

最后再 wrap 一下,出错了就给用户发邮件。放到 crontab 后今天凌晨终于成功的帮我和室友签到了 ;P