本來寫這個玩意兒是想用來自動登入百度,然後根據貼吧內的的排名抓取會員頭像的,比如產生一個貼吧千人頭像圖或萬人頭像圖。也算是練練手。
完成後才發現抓那個貼吧排名完全不需要登入…也好,以後用來做自動一鍵簽到(經常忘打卡),搶二樓什麼的,也不錯~~
如今在部落格上發個文章用不了多長時間就被抄走了,感覺自己能做的也只有在此鄙視一下它們。
廢話太多,容易招人恨,以下是代碼:
#-*- coding:gbk -*-## 類比百度登入 for Python2.7# 其中顯示驗證碼部分 需要使用PIL庫# 需要驗證碼時,會建立一個Tkinter視窗,用於顯示和輸入驗證碼,斷行符號後視窗關閉。#import urllib, urllib2, cookielib, re, timeusername = 'yourusernamehere' #使用者名稱password = 'yourpasswordhere' #密碼cookiefile = '--login-baidu--' #cookie檔案#類比header資訊headers = { "Host":"passport.baidu.com", "Referer":"http://www.baidu.com/cache/user/html/login-1.2.html", "User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36", "Origin":"http://www.baidu.com", """yufang xiao tou. this code by zhengxiao(www.zh30.om)""" "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Cache-Control":"max-age=0", "Connection":"keep-alive" }cookie = cookielib.MozillaCookieJar(cookiefile)#嘗試載入cookie檔案並驗證有效性try: cookie.load(ignore_discard=True, ignore_expires=True) print '讀取登入狀態的cookie成功' #do something... except Exception: #cookie不存在或無效時 開始進行類比登入並重建cookie檔案 opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie)) loginUrl = 'http://www.baidu.com/cache/user/html/login-1.2.html' getTokenUrl = 'https://passport.baidu.com/v2/api/?getapi&class=login&tpl=mn&tangram=true' """www . zh30 . com """ getCodeStringUrl = 'https://passport.baidu.com/v2/api/?logincheck&callback=bdPass.api.login._needCodestringCheckCallback&tpl=mn&charset=UTF-8&index=0&username=' + username + '&isphone=false&time=1436429688644' loginPostUrl = 'https://passport.baidu.com/v2/api/?login' #擷取BAIDUID、token request = urllib2.Request(loginUrl, headers=headers) response = opener.open(request) request = urllib2.Request(getTokenUrl, headers=headers) response = opener.open(request) hasToken = response.read() token = re.search(r'login_token\s*=\s*\'(.+?)\'',hasToken).group(1) #檢查username是否需要驗證碼 request = urllib2.Request(getCodeStringUrl, headers=headers) response = opener.open(request) getCodeString = response.read() codestring = re.search(r'"codestring":"?([^"]+)"?,', getCodeString).group(1) if codestring == 'null' : codestring = '' verifycode = '' else: #需要驗證碼 建立一個tk顯示驗證碼 並提示使用者輸入 genimageUrl = 'https://passport.baidu.com/cgi-bin/genimage?' + codestring + '&v=' + str(long(time.time()*1000)) import io, Tkinter as tk from PIL import Image, ImageTk request = urllib2.Request(genimageUrl, headers=headers) image_bytes = opener.open(request).read() pil_image = Image.open(io.BytesIO(image_bytes)) def presskey(event): global verifycode if event.keycode == 13: verifycode = entry.get() tk_root.destroy() tk_root = tk.Tk() tk_image = ImageTk.PhotoImage(pil_image) label1 = tk.Label(tk_root, text='您的帳號異常,需要輸入驗證碼') label1.pack() label2 = tk.Label(tk_root, image=tk_image) label2.pack() label3 = tk.Label(tk_root, text='輸入驗證碼並按斷行符號確認') label3.pack() entry = tk.Entry(tk_root) entry.bind('<Key>', presskey) entry.pack() tk_root.mainloop() #構造登入表單 data = { "ppui_logintime":"134198", "charset":"utf-8", "codestring":"", "isPhone":"false", "index":"0", "u":"", "safeflg":"0", "staticpage":"http://www.baidu.com/", "loginType":"1", "tpl":"mn", """yufang xiao tou. this code by zhengxiao""" "callback":"parent.bdPass.api.login._postCallback", "mem_pass":"on" } data['token'] = token data['username'] = username data['password'] = password data['codestring'] = codestring data['verifycode'] = verifycode #開始登入 req = urllib2.Request(loginPostUrl, urllib.urlencode(data), headers) result = opener.open(req).read() #驗證登入結果 errno = re.search(r'&error=(\d+)', result).group(1) if errno == '0': print '登入成功' cookie.save(ignore_discard=True,ignore_expires=True) elif errno == '4': print '登入失敗:密碼錯誤' elif errno == '257': print '登入失敗:驗證碼錯誤' else: print '登入失敗' print result #失敗後 列印返回字元 by zh30.com
百度登入時,主要有四個步驟。
第一步:訪問任意百度頁面,得到名為BAIDUID的cookie
第二步:根據cookie去請求得到token(登入時要提交這個值)。
第三步:驗證username是否需要驗證碼。傳回值中如果存在codestring,說明需要驗證碼,然後根據這個codestring請求得到驗證碼。
第四步:提交登入表單,檢查登入狀態,記錄cookie。判斷登入是否成功,可以檢查是否產生名為BDUSS的cookie,鄭曉在這裡判斷的是返回字串中的跳轉連結,成功時error參數為0。
have fun!