第四关
第四关的密码需要从网页获取,1到100,每个数字对应一个密码,最后把它组合起来,然后进行模拟登陆。因为每次访问这个网页,这个网页的内容都在变,所以我们需要循环访问,一直到1到100每个数字都获取到了相应的密码
步骤
-
先访问网址,进行登陆
-
登陆以后,随便输入一个账号密码,我们就会发现它提示:
您输入的密码错误, 请重新输入
偷偷告诉你,密码可以从下面的链接找到
在这里耐心找
http://www.heibanke.com/lesson/crawler_ex03/pw_list/?page=1 -
然后我们把下面网址中的密码提取出来,这样的网页有13个
-
(其实你可以一直访问同一个网址来获取密码,因为就算你访问完了13个网页也得不到完整的密码,要一直循环访问,直到密码完整)
-
最后取得密码,然后进行模拟登陆
-
这里我们可以用多线程进行访问,不用多线程的话,时间大概在900s左右,访问64次的样子,15S左右访问一次
-
用两个线程跑,时间可以缩短到500s左右
-
最多只能用两个线程跑,再多就不行了,网站应该做了限制
代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*_
import requests
import re
import os
import threading
from datetime import datetime
#注:需要填写你的账号密码 在 self.data_login部分
class Login(object):
def __init__(self):
self.session = requests.Session()
self.headers = {
'Host': 'www.heibanke.com',
'User-Agent': 'Mozilla/5.0 (iPad; CPU OS 12_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) CriOS/68.0.3440.83 Mobile/16A5345f Safari/604.1',
'Referer': 'http://www.heibanke.com/lesson/crawler_ex03/'
}
self.url_get = 'http://www.heibanke.com/lesson/crawler_ex03/'
self.url_login = ''
# 获取页面的基本网址,后面再加上数字来访问
self.url_list_base = 'http://www.heibanke.com/lesson/crawler_ex03/pw_list/?page='
self.url_list = ''
self.data_test = {
'csrfmiddlewaretoken': '',
'username': 'user',
'password': ''
}
self.data_login = {
'csrfmiddlewaretoken': '',
'username': '你的账号',
'password': '你的密码'
}
# 用列表生成式加list()函数生成一个0到100的数组
# 用来判断0到100每个位置对应的密码是否都获取到了
self.nums = list([num for num in range(1, 101)])
self.i = 1
self.d_list = {}
# 设置锁,防止修改冲突
self.lock = threading.Lock()
# 取cookies
def get_cookies(self):
# 要完成这个题,首先需要登陆网站,假如你没登陆网站,那么访问这个网址的时候会跳转到登陆界面
response = self.session.get(url=self.url_get, headers=self.headers)
if self.data_login['csrfmiddlewaretoken'] == '':
self.data_login['csrfmiddlewaretoken'] = response.cookies['csrftoken']
# 已经跳转到登陆界面了,我们把登陆url提取出来
return response.url
self.data_test['csrfmiddlewaretoken'] = response.cookies['csrftoken']
# 登陆账号
def login(self):
response = self.session.post(
url=self.url_login, headers=self.headers, data=self.data_login)
# 若登陆成功,会跳转到http://www.heibanke.com/lesson/crawler_ex03/
if response.url == self.url_get:
print('登陆成功!')
return True
else:
print('账号密码错误!')
return False
# 取单个密码页面
def get_page(self):
response = self.session.get(url=self.url_list, headers=self.headers)
content = response.text
patter = re.compile(
'<tr.*?<td.*?title=.*?pos.*?>(.*?)</td>.*?<td.*?title=.*?val.*?>(.*?)</td>.*?</tr>', re.S)
results = re.findall(patter, content)
# results返回的值是类似这样的
#[('89', '6'), ('83', '6'), ('25', '5'), ('64', '1'), ('95', '2'), ('56', '3'), ('74', '8'), ('75', '6')]
for result in results:
yield result
# 取出密码
def get_password(self):
l = len(self.nums)
while l > 0:
# 因为每个页面都在变,其实可以不用从1到13,直接同一个页面重复访问就行
page = self.i % 13
self.url_list = self.url_list_base + str(page)
for result in self.get_page():
# result是一个元组,类似('89', '6')
self.d_list[result[0]] = result[1]
# 假如已经存入字典了,那么就在列表中删掉字典的键
num = int(result[0])
if num in self.nums:
self.nums.remove(num)
l = len(self.nums)
nowtime = datetime.now()
# strftime()用来格式化datetiem对象,%X是转为当前时间
print('当前时间', nowtime.strftime('%X'))
print('这是第%s次请求,密码长度为%s' % (self.i, (100-l)))
print('还未取得密码的数字:%s' % self.nums)
self.i += 1
# 拼接密码
def sorting_password(self):
# 把字典的key取出来,转成列表,然后对列表进行排序
# 需要先转成int类型的,因为我们需要排序,str进行排序跟int进行排序的顺序是不一样的,可以自己试试
# 如l=['1','2','6','3','4','10','5'],是str类型的,排序后是['1', '10', '2', '3', '4', '5', '6']
keys = (int(key) for key in self.d_list.keys())
keys = sorted(keys)
password = ''
for key in keys:
password += self.d_list[str(key)]
self.data_test['password'] = password
# 模拟登陆
def post_page(self):
response = self.session.post(
url=self.url_get, headers=self.headers, data=self.data_test)
content = response.text
text = re.findall('<h3>(.*?)</h3>', content, re.S)[0]
print('用户名:', self.data_test['username'], '----密码: ', self.data_test['password'],
'---csf:', self.data_test['csrfmiddlewaretoken'], '提示信息:', text)
# 多线程
def run_thread(self):
#最多只能两个线程跑,网站设置了限制,多了就不行了
t1 = threading.Thread(target=self.get_password)
t2 = threading.Thread(target=self.get_password)
t1.start()
t2.start()
t1.join()
t2.join()
# 进行闯关
def main(self):
self.url_login = str(self.get_cookies())
if self.login():
# 因为登陆成功了,所以重新设置cookies
self.get_cookies()
self.run_thread()
self.sorting_password()
self.post_page()
print('-'*20+'end'+"-"*20)
if __name__ == "__main__":
star = datetime.now()
login = Login()
login.main()
end = datetime.now()
total_time = (end-star).seconds
print('总耗时%s秒' % (total_time))
#密码 4895069524432954894613647990394874326048437134877661813696344916326470648993670283105253381901613579
结语:
源码: 点我
欢迎关注我的公众号
疯子的Python笔记