接上一篇模拟登录之果壳网。果壳网的模拟登录较为简单,表单的结构不复杂,而有些网站会给密码和账号加密
、再添加一些额外验证字段
后才进行验证,有些难度,这篇用以记录拉勾网模拟登录过程,前期准备和文章模拟登录之果壳网一样,移步{% post_link 模拟登录之果壳网 %}。
思路
- 分析表单,找出需要提交的字段
- 经过分析,大多数提交字段都可以在 html 源码中找到
- 密码经过 md5 加密
分析表单
拉勾网登录 url:https://passport.lagou.com/login/login.html
登录账号:[email protected]
登录密码:123456789
由于之前实验了多次,所以出现拉钩官网重置密码的提示,可以忽略。
点击登录后的信息:
重要的有两个,login.json
和 create?from=register&refresh=1506950234998
。
先查看login.json
:
提交的方法为 POST
,说明表单提交的目的地就是这个地址,还有需要提交的表单字段:
多达 8 项表单字段,红色方框内以 X- 开头
的都可以在 html 源码
中找到,值得注意的是橙色方框内的 password
字段并不是我们所填的密码 123456789
,而是一串很长的且不是由用户输入的字符串,这就是经过加密的密码,经过某种加密算法生成。
再看create?from=register&refresh=1506950234998
:
这就是验证码的地址,其实在一开始登录界面时并没有要求输入验证码,但是既然在调试器中发现了,并且为了此次模拟登录的成功,就要将它添加到模拟登录的逻辑中。
寻找表单字段
X-Requested-With
在多次试验后,此字段为固定值:X-Requested-With : XMLHttpRequest
X-Anit-Forge-Code 和 X-Anit-Forge-Token
这两个值在 html 源码
中找到,可以使用正则表达式筛选出来:
# 获取 X-Anit-Forge-Code 和 X-Anit-Forge-Token
def get_anti_Code_Token():
url = 'https://passport.lagou.com/login/login.html'
response = session.get(url, headers=headers)
match_obj = re.match(r".*?Forge_Token = '(.*?)'.*Forge_Code = '(.*?)'.*", response.text, re.DOTALL)
if match_obj:
code = match_obj.group(2)
token = match_obj.group(1)
return code, token
else:
'failed to match code and token!'
isValidate
此字段为固定值,isValidate: true
submit
此字段为空
request_form_verifyCode
- 验证码,通过访问
https://passport.lagou.com/vcode/create?from=register&refresh=当前时间秒数
获得,类似上一篇模拟登录之果壳网,获取验证码方法相似:
# 获取验证码,生成当前时间,拼凑好url,将 response 的内容(也就是验证码图片)下载到本地,在通过 PIL 库展示给用户进行输入
def get_captcha():
url = 'https://passport.lagou.com/vcode/create?from=register&refresh={}'.format(str(int(time.time() * 1000)))
response = session.get(url, headers=headers)
with open('captcha.jpg', 'wb') as f:
f.write(response.content)
f.close()
from PIL import Image
try:
captcha_image = Image.open('captcha.jpg')
captcha_image.show()
captcha_image.close()
except:
print 'captcha.jpg not found!'
code = raw_input('please check the captcha code and enter it:')
return code
username
直接输入
password
password 经过 md5 加密
,在 html 源码
中,查看每一个 js 文件
,然后找到了拉勾网对密码加密的具体方法:
主要分析红色方框两行代码,分为以下几步加密了用户输入的密码:
- 定义一个 c 为字符串
"veenike"
- 用
md5()
方法加密用户输入的密码,再将此时得到的值用hexdigest()
方法转成另一个字符串,字面意思大概是转换成一串16 进制数
,暂且将它命名为first_encrypt
- 此时再将 first_encrypt 与 c 相加,公式为
c + first_encrypt + c
,此时得到的结果给它命名为rude
- 此时再
重复第 2 步
,md5()
再次编码,hexdigest()
再次编码,就得到最后结果
写成 python 代码:
def encrypt_password(password):
stable_word = 'veenike'
first_encrypt = hashlib.md5(password).hexdigest()
rude = stable_word + first_encrypt + stable_word
second_encrypt = hashlib.md5(rude).hexdigest()
print second_encrypt
return second_encrypt
到这里,所有的表单字段都已经找到,开始写登录主函数。
登录
一些说明:
- 基本爬虫必备 User-Agent
- 用到 requests session(),保证连接持续性
- cookielib 保存模拟登录成功后的 cookies 到本地,之后的登录读取此 cookies,免账号密码登录
登录主函数示例:
def lagou_login(phone_number, password):
url = 'https://passport.lagou.com/login/login.json'
post_data = {
'isValidate': 'true',
'username': phone_number,
'password': # 加密方法函数,
'request_form_verifyCode': # 获取验证码,
'submit': ''
}
code_token = # 获取两个 token 值
token_headers = # user-agent 模仿浏览器
token_headers['X-Anit-Forge-Code'] = code_token[0]
token_headers['X-Anit-Forge-Token'] = code_token[1]
token_headers['X-Requested-With'] = 'XMLHttpRequest'
token_headers['Referer'] = 'https://passport.lagou.com/login/login.html' # 在浏览器找到添加
response = session.post(url, data=post_data, headers=token_headers) # 用 session 保持连续性
session.cookies.save() # 保存登录成功后的 cookies
pass
Referer
也是要提交的表单字段之一,和其他字段一样,在调试器中找到。
等代码运行完后看看保存到本地的 cookies
:
目测有效期为一个星期左右。
测试 cookies 是否有效
获取到 cookies 后,因为不知道 cookies 是否有效,此时有必要写一个函数来验证它的有效性,拿着这个 cookies 去访问一个需要登录后才能访问的 url,比如个人中心,这些 url 没有登录是不能访问的:
session = requests.session()
session.cookies = cookielib.LWPCookieJar('cookies.txt')
try:
session.cookies.load(ignore_discard=True) #加载cookies
except:
print 'cookies failed to load!'
else:
print 'cookies has been loading!'
def is_login():
url = 'https://www.lagou.com/mycenter/invitation.html'
response = session.get(url, headers=headers)
if response.status_code != 200:
return False
else:
return True
返回状态码为 200
时,就说明此 cookies 有效。
完整代码地址: github