Python爬虫闯关-4

第四关

第四关网址:http://www.heibanke.com/lesson/crawler_ex03/

第四关的密码需要从网页获取,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笔记

公众号二维码.jpg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值