最近做项目,需要用到自动登录淘宝,正好在学习 python, 整网络爬虫, 所以就尝试着写一个脚本, 自动解决。有相同需求的小伙伴可以参考下
Python 是一种面向对象、解释型计算机程序设计语言,由 Guido van Rossum 于 1989 年底发明,第一个公开发行版发行于 1991 年。Python 语法简洁而清晰,具有丰富和强大的类库。它常被昵称为胶水语言,它能够把用其他语言制作的各种模块(尤其是 C/C++)很轻松地联结在一起。
一个小项目自动登录淘宝联盟抓取数据,由于之前在 Github 上看过类似用 Python 写的代码因此选择用 Python 来写,第一次用 Python 正式写程序还是被其 "简单" 所震撼,当然用的时候还是对其(2.7 版)编码、迁移环境等问题所困扰,还好后来都解决了。
言归正传,抓取淘宝联盟的数据首先要解决的就是登录的问题,之前一般会碰到验证码的困扰,现在支持二维码扫码登录反而简单了,以下是登录的 Python 代码,主要是获取二维码打印,然后不断的检查扫码状态,如果过期了重新请求二维码(主要看逻辑,由于有些通用方法做了封装所以不保证能直接执行)
- 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://login.taobao.com/member/taobaoke/login.htm?is_login=1&_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 默认用增量的方式进行更新
- 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
- 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 都没有获得服务器方更新的票据,不知道这一块大家有没有可以提供的思路。
来源: http://www.phperz.com/article/17/0318/319076.html