美文网首页我爱编程
Python 爬虫闯关(第四关)-续

Python 爬虫闯关(第四关)-续

作者: hoxis | 来源:发表于2018-08-21 10:38 被阅读1次

    上回 Python 爬虫闯关(第四关) 中,我们发现程序执行过程非常漫长,将近 24 分钟啊!另外页面也有提示说:网页会慢半拍。那么也许需要一个高效率的方法进行解析,多线程?

    题意再理解

    本关的题目内容,这里再简单说一下:不清楚的翻下历史。

    页面给出了闯关所需密码的随机位置,以及该位置的值,我们需要遍历所有页面,获取到 100 位的密码。

    其中,值得注意的两点:

    1. 每一页的载入速度非常慢(正如页面内容所述),大约需要 15 秒,这是黑板课后台故意设置的;
    2. 每个页面是动态加载的,每次获取到的密码的位置并不是相同的,也就是检索完 13 页数据也不能得到 100 位的密码,需要重复检索以得到其余位置的密码。

    由此可见,必须使用多线程才能迅速得到密码。

    闯关思路

    多线程编程使用 threading 模块,登录过程和第 3 关一样,基本只需要在第 3 关的基本上增加获取密码的功能就可以了。

    1. 初始化一个字典,用来存放密码;
    2. 每个线程都不断获取页面的全部位置和值,并将它们更新到字典中;
    3. 判断字典长度,如果字典的长度小于 100,则继续抓取页面数据并跟新字典,直到长度满足 100;
    4. 将字典中的数据转换为字符串,然后通过 post 提交到服务器进行登录;

    实现

    # coding=utf-8
    
    import requests, bs4
    import threading
    import time
    
    def login():
        # 登录URL,获取cookie
        login_url = 'http://www.heibanke.com/accounts/login/?next=/lesson/crawler_ex03/'
        login_data = {'username':'liuhaha', 'password':'123456'}
    
        # 获取默认cookie
        response = requests.get(url)
        if response.status_code == 200:
            print('Welcome')
        cookies = response.cookies
    
        # 登录 
        login_data['csrfmiddlewaretoken'] = cookies['csrftoken']
        login_response = requests.post(login_url, allow_redirects=False, data=login_data, cookies=cookies)
        if login_response.status_code == 200:
            print('login sucessfully')
    
        return login_response.cookies
    
    def getPassword(page):
        global pwd_data
        payload['page'] = page
        print(threading.currentThread().getName() + ', loading %s?page=%s ...' %(pwd_url, page))
        pwd_response = requests.get(pwd_url, cookies=cookies, params=payload)
    
        soup = bs4.BeautifulSoup(pwd_response.text, "html.parser")
    
        pwd_pos = soup.findAll('td', {'title':'password_pos'})
        pwd_value = soup.findAll('td', {'title':'password_val'})
    
        for index in range(len(pwd_pos)):
            pwd_data[int(pwd_pos[index].getText())] = pwd_value[index].getText()
        print(threading.currentThread().getName() + ', now the pwd_data length is %s' % len(pwd_data))
        
    class MyThread(threading.Thread):  
        def __init__(self, s):  
            threading.Thread.__init__(self)
            self.s = s  
          
        def run(self):  
            global pwd_data
            global count
            while len(pwd_data) < 100:
                count += 1
                print('The sub-thread has run %s times' % count)
                getPassword(count % 13)
                  
    if __name__ == '__main__':  
        start = time.time()
        payload = {}
        # 存放密码键值对
        pwd_data = {}
        # 记录运行次数
        count = 0
    
        # 题目URL
        url = 'http://www.heibanke.com/lesson/crawler_ex03/'
         # 获取密码URL
        pwd_url = 'http://www.heibanke.com/lesson/crawler_ex03/pw_list/'
       
        # 获取登录成功后的cookie
        cookies = login()
    
        threads = []
        for i in range(0, 5):  # 线程数,可自定义  
            thread = MyThread(cookies)
            threads.append(thread)
            thread.start()
        
        # 等待所有线程完成
        for thread in threads:
            thread.join()
        
        # 拼接password
        password = ''
        for key in sorted(pwd_data.keys()):
            password = password + pwd_data[key]
        print(password)
    
        # 重新登录
        playload = {'username':'liuhaha', 'password':password}
        playload['csrfmiddlewaretoken'] = cookies['csrftoken']
    
        r = requests.post(url, data=playload, cookies=cookies)
    
        print(u'执行结果:' + str(r.status_code))
    
        if r.status_code == 200:
            # print(r.text)
            if u"成功" in r.text:
                print(u'闯关成功!密码为:' + password)
                print(u'用时 %s s' % (time.time() - start))
                # break
        else:
            print(u'Failed')
    

    多线程下,也许是网站限制,发现不管设置几个线程,运行时间总是在 470s 左右,不到 8 分钟,虽说时间仍然很长,但是比单线程版本已经有了明显提升。

    有同学后台问我,这个网站怎么设置了多个线程不管用啊,其实我也解决不了,我们了解原理不就好了~


    如果觉得有用,欢迎关注我的微信,一起学习,共同进步,不定期推出赠书活动~

    你的关注是对我最大的鼓励!你的关注是对我最大的鼓励!

    最近搜集到慕课网视频,视频内容涵盖 Python、Java、PHP、前端、小程序、算法、架构、数据库等等!关注本公众号,后台回复「慕课网」即可获取下载地址。

    相关文章

      网友评论

        本文标题:Python 爬虫闯关(第四关)-续

        本文链接:https://www.haomeiwen.com/subject/qlediftx.html