一个小项目自动登录淘宝联盟抓取数据,由于之前在Github上看过类似用Python写的代码因此选择用Python来写,第一次用Python正式写程序还是被其“简单”所震撼,当然用的时候还是对其(2.7版)编码、迁移环境等问题所困扰,还好后来都解决了。
言归正传,抓取淘宝联盟的数据首先要解决的就是登录的问题,之前一般会碰到验证码的困扰,现在支持二维码扫码登录反而简单了,以下是登录的Python代码,主要是获取二维码打印,然后不断的检查扫码状态,如果过期了重新请求二维码(主要看逻辑,由于有些通用方法做了封装所以不保证能直接执行)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
def getQRCode(enableCmdQR): payload = { '_ksTS' : str (time.time()), 'from' : 'alimama' } qrCodeObj = utils.fetchAPI( 'https://qrlogin.taobao.com/qrcodelogin/generateQRCode4Login.do' , payload, "json" , None , True , True ) print (qrCodeObj) utils.printQRCode( 'http:' + qrCodeObj[ 'url' ], enableCmdQR) lgToken = qrCodeObj[ 'lgToken' ] return lgToken def login(enableCmdQR = False ): lgToken = getQRCode(enableCmdQR) code = 0 successLoginURL = "" while code ! = 10006 : payload = { 'lgToken' : lgToken, 'defaulturl' : 'http%3A%2F%2Flogin.taobao.com%2Fmember%2Ftaobaoke%2Flogin.htm%3Fis_login%3D1&_ksTS=' + str ( time.time())} rObj = utils.fetchAPI( 'https://qrlogin.taobao.com/qrcodelogin/qrcodeLoginCheck.do' , payload, "json" , True , False ) code = int (rObj[ 'code' ]) if 10000 = = code: # print("请扫描二维码登录") continue elif 10001 = = code: print ( "已扫描二维码,请在确认登录" ) elif 10004 = = code: print ( "已过期请重新扫描" ) login() elif 10006 = = code: successLoginURL = rObj[ "url" ] print ( "登录成功,正在跳转" ) else : print ( "未知错误,退出执行" ) sys.exit( 0 ) time.sleep( 5 ) print "登录成功跳转:" + successLoginURL r = utils.fetchAPI(successLoginURL, None , "raw" , True , False , True ) utils.fetchAPI(r.headers[ 'Location' ], None , "raw" , True , True , False ) |
解决登录问题接下去就要解决保存状态的问题,Python的Requests库非常强大,如果简单的话可以直接使用request.session来进行会话操作,但由于项目中的很多操作是异步的因此需要解决cookie的存储和读取,使用pickel进行对像的序列化和反序列化。其中保存cookie默认用增量的方式进行更新
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
def save_cookies(cookies, overWrite = False ): try : currentCookie = requests.utils.dict_from_cookiejar(cookies) if len (currentCookie) < 1 : return oldCookie = requests.utils.dict_from_cookiejar(load_cookies()) with open (config.COOKIE_FILE, 'w' ) as f: if not overWrite: cookieDict = dict (oldCookie, * * currentCookie) else : cookieDict = requests.utils.dict_from_cookiejar(cookies) pickle.dump(cookieDict, f) print 'Saved cookie' print cookieDict f.close() except : print 'Save cookies failed' , sys.exc_info()[ 0 ] sys.exit( 99 ) def load_cookies(): try : with open (config.COOKIE_FILE, 'r' ) as f: cookies = requests.utils.cookiejar_from_dict(pickle.load(f)) f.close() except : cookies = [] return cookies |
封装好之后,在requests.Session请求时加载cookie并保存cookie
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
s = requests.Session() # 统一请求API def fetchAPI(url, params = None , resultFormat = "text" , isNeedCookie = True , allowRedirects = True , saveCookie = False , method = 'GET' ): try : cookies = load_cookies() if 'POST' = = method: response = s.post(url, data = params, headers = config.Headers, cookies = cookies) else : response = s.get(url, params = params, headers = config.Headers, cookies = cookies, allow_redirects = allowRedirects) if "json" = = resultFormat: result = response.json() elif "raw" = = resultFormat: result = response else : result = response.text # if saveCookie: # print 'save cookie:' + str(response.cookies) save_cookies(response.cookies) return result except Exception, e: print e return False |
这两步做好之后基本后续的请求就直接使用统一的API请求方法即可,效果也非常不错,运行效果截图:
当然还有一个问题未解决:如何在session过期之后如何自动重新申请(不确定淘定是否支持),由于淘宝是用统一登录而且是独立的服务因此通过浏览器自动刷新或者请求过程中不断去更新cookie都没有获得服务器方更新的票据,不知道这一块大家有没有可以提供的思路。