第一次写Python爬虫脚本,欢迎批评指教。
看了几个其他人写的脚本需要获取pcid、pubkey等,但我发现从新浪通行证页面登录时密码还是明文的,于是从这里入手。
首先用浏览器打开https://login.sina.com.cn/sso/login.php,打开开发者工具,输入登陆信息并提交,找到提交表单时的POST方法。
请求网址为https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)&_=1446479075883,最后的参数是客户端的Unix时间(毫秒级)。之后的请求网址也都包含时间参数。
表单中su为加密的用户名,sp为明文密码:
用户名加密方法可以从http://login.sina.com.cn/js/sso/ssologin.js找到:
username=sinaSSOEncoder.base64.encode(urlencode(username));
Python实现:
base64.b64encode(urllib.parse.quote(username).encode(encoding="utf-8")).decode(encoding="utf-8")
用和浏览器相同的表单数据和header数据去请求相同的URL。
# Initialize POST data.
postdata = {
'entry':'sso',
'gateway':'1',
'from':'null',
'savestate':'30',
'userticket':'0',
'pagerefer':'',
'vsnf':'1',
'su':username,
'service':'sso',
'sp':password,
'sr':'1280*800',
'encoding':'UTF-8',
'cdult':'3',
'domain':"sina.com.cn",
'prelt':'0',
'returntype':'TEXT'
}
postdata = urllib.parse.urlencode(postdata).encode(encoding='utf-8')
# Initialize hearders.
headers = {
'Accept':'*/*',
'Accept-Language':'zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4,zh-TW;q=0.2,es;q=0.2',
'Accept-Encoding':'gzip, deflate',
'Connection':'keep-alive',
'Content-Length':'212',
'Content-Type':'application/x-www-form-urlencoded',
'Host':'login.sina.com.cn',
'Origin':'http://login.sina.com.cn',
'Referer':'http://login.sina.com.cn/signup/signin.php?entry=sso',
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'
}
# Create cookies, handler and opener.
cookie = http.cookiejar.MozillaCookieJar(cookie_file)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
# Open Sina passport sso login page. Use POST method.
url = 'https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)&_=' + str(int(time.time()*1000))
req = urllib.request.Request(url, postdata, headers)
response = opener.open(req)
返回了一组json数据:
{"retcode":"0","ticket":"ST-MjY0NjY0OTg5NA==-1446506651-gz-D68C4A944B958CF1651E6C65B930760E","uid":"2646649894","nick":"\u7528\u62372646649894","crossDomainUrlList":["https:\/\/passport.weibo.com\/wbsso\/login?ticket=ST-MjY0NjY0OTg5NA%3D%3D-1446506651-gz-79B6F2B5E77E4B17AE5A537A118D3F84&ssosavestate=1478042651","https:\/\/crosdom.weicaifu.com\/sso\/crosdom?action=login&savestate=1478042651","https:\/\/passport.weibo.cn\/sso\/crossdomain?action=login&savestate=1"]}
一开始看到retcode是0我以为登陆成功了,然后尝试访问微博发现返回的还是登陆页面。对比浏览器的请求发现,json里的每个网址都要Get一遍才能得到正确的cookies。另外json里的网址不完整,对比浏览器请求后补全。
urls[0] = 'https:' + urls[0] + '&callback=sinaSSOController.doCrossDomainCallBack&scriptId=ssoscript0&client=ssologin.js(v1.4.15)&_=' + str(int(time.time()*1000))
req = urllib.request.Request(urls[0])
opener.open(req)
最后请求新浪通信证的个人页面,显示账户信息就表明登陆成功了,接着打开一个微博页面。
url = 'http://login.sina.com.cn/member/my.php?entry=sso'
req = urllib.request.Request(url)
response = opener.open(req)
print(response.read().decode('gb2312','ignore'))
author_weibo = opener.open('http://weibo.com/uglycheri')
print(author_weibo.read().decode('utf-8','ignore'))
保存cookies,之后可以用cookies直接登陆。
cookie.save(ignore_discard=True, ignore_expires=True)