作者: xiaoyu
微信公众号: Python 数据科学
知乎: python 数据分析师 https://zhuanlan.zhihu.com/pypcfx
模拟登录想必大家已经熟悉了, 之前也分享过关于模拟登录 wechat 和京东的实战, 链接如下:
Python 爬虫之模拟登录 wechat https://mp.weixin.qq.com/s?__biz=MzUzODYwMDAzNA==&mid=2247483878&idx=1&sn=8f7d492d8bb521a84d35fc93c3cca4ac&chksm=fad476ebcda3fffde6d4dd07e67aefe8498ff29c8006690078634fdd13b29bd1dcccbadbc739#rd
Python 爬虫之模拟登录京东商城 https://mp.weixin.qq.com/s?__biz=MzUzODYwMDAzNA==&mid=2247483823&idx=1&sn=fa741c8458bdf9857d06ad281fe26c4c&chksm=fad476a2cda3ffb43c2d87473fe2d79033b83bb0527e7e5bada70cea7da4cf4ef07ebfb5d15b#rd
介绍
本篇, 博主将分享另一个模拟登录的实例供大家分享, 模拟登录拉勾网.
废话不多说了, 还是老套路使用 fiddler 或者开发者工具来帮助我们完成模拟登录的整个过程, 通过观察 http 的 headers 请求头来模拟 post 请求各种参数. 当然如何找到这些参数就显得尤为重要了, 一些参数是时间戳, 而一些参数是动态加密的.
对于这些参数的获取, 有几个常用方法:
请求 Ajax 获取参数;
查看页面源码;
解密参数;
本篇的模拟登录对象拉钩网就对登录密码就进行了 md5 双重加密, 因此我们只须双重加密获得相应的密码就可以了.
代码部分
需要的 package
- import re
- import os
- import time
- import json
- import sys
- import subprocess
- import requests
- import hashlib
- from bs4 import BeautifulSoup
建立一个类
- class Lagou_login(object):
- def __init__(self):
- self.session = requests.session()
- self.CaptchaImagePath = os.path.split(os.path.realpath(__file__))[0] + os.sep + 'captcha.jpg'
- self.HEADERS = {'Referer': 'https://passport.lagou.com/login/login.html',
- 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) ApplewebKit/537.36'
- '(KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36'
- 'Core/1.53.4882.400 QQBrowser/9.7.13059.400',
- 'X-Requested-With': 'XMLHttpRequest'}
session: 创建持久对话
CaptchaImagePath: 验证码的 path
HEADERS: 请求头
登录密码加密
- def encryptPwd(self, passwd):
- # 对密码进行了 md5 双重加密
- passwd = hashlib.md5(passwd.encode('utf-8')).hexdigest()
- # veennike 这个值是在 js 文件找到的一个写死的值
- passwd = 'veenike'+passwd+'veenike'
- passwd = hashlib.md5(passwd.encode('utf-8')).hexdigest()
- return passwd
对用户密码进行双重 md5 加密.
获取请求 token
- def getTokenCode(self):
- login_page = 'https://passport.lagou.com/login/login.html'
- data = self.session.get(login_page, headers= self.HEADERS)
- soup = BeautifulSoup(data.content, "lxml", from_encoding='utf-8')
- '''
要从登录页面提取 token,code, 然后在头信息里面添加
- <!-- 页面样式 --><!-- 动态 token, 防御伪造请求, 重复提交 -->
- <script type="text/javascript">
- window.X_Anti_Forge_Token = 'dde4db4a-888e-47ca-8277-0c6da6a8fc19';
- window.X_Anti_Forge_Code = '61142241';
- </script>
- '''anti_token = {'X-Anit-Forge-Token':'None','X-Anit-Forge-Code':'0'}
- anti = soup.findAll('script')[1].getText().splitlines()
- anti = [str(x) for x in anti]
- anti_token['X-Anit-Forge-Token'] = re.findall(r'= \'(.+?)\'', anti[1])[0]
- anti_token['X-Anit-Forge-Code'] = re.findall(r'= \'(.+?)\'', anti[2])[0]
- return anti_token
这部分可以从 headers 请求头参数中看到, 并且在页面源码中可以直接查找到.
验证码处理
- def getCaptcha(self):
- captchaImgUrl = 'https://passport.lagou.com/vcode/create?from=register&refresh=%s' % time.time()
- # 写入验证码图片
- f = open(self.CaptchaImagePath, 'wb')
- f.write(self.session.get(captchaImgUrl, headers=self.HEADERS).content)
- f.close()
- # 打开验证码图片
- if sys.platform.find('darwin')>= 0:
- subprocess.call(['open', self.CaptchaImagePath])
- elif sys.platform.find('linux')>= 0:
- subprocess.call(['xdg-open', self.CaptchaImagePath])
- else:
- os.startfile(self.CaptchaImagePath)
- # 输入返回验证码
captcha = input("请输入当前地址 (% s) 的验证码:" % self.CaptchaImagePath)
- print('你输入的验证码是:% s' % captcha)
- return captcha
此处验证码还是通过请求下载到本地然后手动输入的方法完成
引入 subprocess 将会自动打开图片而不用手动点开(对应于 3 种常用操作系统)
登陆操作
- def login(self, user, passwd, captchaData=None, token_code=None):
- postData = {'isValidate': 'true',
- 'password': passwd,
- # 如需验证码, 则添加上验证码
- 'request_form_verifyCode': (captchaData if captchaData!=None else ''),'submit':'',
- 'username': user
- }
- login_url = 'https://passport.lagou.com/login/login.json'
- #头信息添加 token
- login_headers = self.HEADERS.copy()
- token_code = self.getTokenCode() if token_code is None else token_code
- login_headers.update(token_code)
- # data = {"content":{"rows":[]},"message":"该帐号不存在或密码错误, 请重新输入","state":400}
- response = self.session.post(login_url, data=postData, headers=login_headers)
- data = json.loads(response.content.decode('utf-8'))
- if data['state'] == 1:
- return response.content
- elif data['state'] == 10010:
- print(data['message'])
- captchaData = self.getCaptcha()
- token_code = {'X-Anit-Forge-Code' : data['submitCode'], 'X-Anit-Forge-Token' : data['submitToken']}
- return self.login(user, passwd, captchaData, token_code)
- else:
- print(data['message'])
- return False
通过请求 login_url 接口 api 判断登录是否成功
将获取的和处理的各种参数通过 post 发出请求
使用 json 解析返回数据
判断 state 参数
主函数
- if __name__ == "__main__":
- username = input("请输入你的手机号或者邮箱 \ n>>>:")
- passwd = input("请输入你的密码 \ n>>>:")
- lg = Lagou_login()
- passwd = lg.encryptPwd(passwd)
- data = lg.login(username, passwd)
- if data:
- print(data)
- print('登录成功')
- else:
- print('登录不成功')
登录结果显示
相信大家已经 get 到如何使用模拟登录了, 下面是成功登录的显示结果:
链接: https://github.com/xiaoyusmd/Lagou_login
来源: https://segmentfault.com/a/1190000014683856