打开网站,这里我选择的是动漫专区的壁纸,我们的目的是把所有动漫壁纸爬下来,我们发现一共有98页图片
很多人学习python,不知道从何学起。 很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。 很多已经做案例的人,却不知道如何去学习更加高深的知识。 那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!??¤QQ群:623406465
所以我们要做的是观察每页图片链接的关系,我们打开第二页图片观察 发现两页图片的链接分别是https://www.h128.com/pc/anime/0/2/1920x1080/t/1.html https://www.h128.com/pc/anime/0/2/1920x1080/t/2.html 我们发现两个网页只有t/后面的数据不同由此我们观察后面几页,最终我们发现/t/后面的数字就是代表页数,所以在最开始我们建立一个函数来存放我们需要的网页链接 如下:
page_links_list = ['https://www.h128.com/pc/anime/0/2/1920x1080/t/1.html'] def GetUrls(page_links_list): pages = int(input("请输入你想爬取的页数:")) if pages > 1: for page in range(2, pages + 1): url = 'https://www.h128.com/pc/anime/0/2/1920x1080/t/' + str(page) + '.html' page_links_list.append(url) else: page_links_list = page_links_list然后就是我们多线程的应用了,我们要用的是python的threading模块首先需要导入threading
import threading首先建立一个glock 用来控制
gLock = threading.Lock()**threading 提供了 Lock 类,该类能够在某个线程访问某个变量的时候对变量加锁,此时其它线程就不能访问该变量,直到该 Lock 被释放其它线程才能够访问该变量 ** 我们爬虫需要生产者进程和消费者进程,生产者的线程专门用来生产一些数据,然后存放到一个中间的变量中。消费者再从这个中间的变量中取出数据进行消费。但是因为要使用中间变量,中间变量经常是一些全局变量,因此需要使用锁来保证数据完整性。在这个代码中生产者进程负责来获取我们图片的url,而消费者进程的目的是下载图片。生产者代码如下:
class Generant(threading.Thread): def run(self): while len(page_links_list) > 0: gLock.acquire() #上锁 page_url = page_links_list.pop() gLock.release() #释放锁 r = requests.get(page_url,headers = headers) r.raise_for_status() r.encoding = r.apparent_encoding a = re.findall('<img src="https:(.*?)" alt',r.text) gLock.acquire() #上锁 for i in a : x = 'https:' + i x = x.replace('w_487', 'w_1421').replace('h_274', 'h_799') img_links_list.append(x) gLock.release() #释放锁消费者代码如下
class Consumer(threading.Thread,): def run(self): while True: gLock.acquire() if len(img_links_list) == 0: gLock.release() continue else: img_url = img_links_list.pop() gLock.release() filename = img_url.split('?')[0].split('/')[-1] r = requests.get(img_url) print('正在下载:', filename) path = './picture/' + filename with open(path,'wb') as f: f.write(r.content) f.close() if len(img_links_list) == 0: end = time.time() print("消耗的时间为:", (end - start)) exit()最后的代码就是启动线程
for x in range(5): Generant().start() for x in range(5): Consumer().start()观看运行结果:
这里是下载了50页图片的时间,比起单线程还是很快的。 最后附上完整代码 下面展示一些 内联代码片。
import threading import requests import re import time import os page_links_list = ['https://www.h128.com/pc/anime/0/2/1920x1080/t/1.html'] img_links_list = [] headers = { "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36" } def GetUrls(page_links_list): pages = int(input("请输入你想爬取的页数:")) if pages > 1: for page in range(2, pages + 1): url = 'https://www.h128.com/pc/anime/0/2/1920x1080/t/' + str(page) + '.html' page_links_list.append(url) else: page_links_list = page_links_list gLock = threading.Lock() class Generant(threading.Thread): def run(self): while len(page_links_list) > 0: gLock.acquire() #上锁 page_url = page_links_list.pop() gLock.release() #释放锁 r = requests.get(page_url,headers = headers) r.raise_for_status() r.encoding = r.apparent_encoding a = re.findall('<img src="https:(.*?)" alt',r.text) gLock.acquire() #上锁 for i in a : x = 'https:' + i x = x.replace('w_487', 'w_1421').replace('h_274', 'h_799') img_links_list.append(x) gLock.release() #释放锁 class Consumer(threading.Thread,): def run(self): while True: gLock.acquire() if len(img_links_list) == 0: gLock.release() continue else: img_url = img_links_list.pop() gLock.release() filename = img_url.split('?')[0].split('/')[-1] r = requests.get(img_url) print('正在下载:', filename) path = './picture/' + filename with open(path,'wb') as f: f.write(r.content) f.close() if len(img_links_list) == 0: end = time.time() print("消耗的时间为:", (end - start)) exit() if __name__ == '__main__': GetUrls(page_links_list) if os.path.exists('./picture'): print("文件已存在") else: os.mkdir('./picture') start = time.time() for x in range(5): Generant().start() for x in range(5): Consumer().start()最后如果想要全站的图片只要把链接改一下就OK