python爬虫(三)——多线程+正则匹配下载图片(wallheaven图片网站)

it2023-05-16  72

多线程+正则匹配下载图片(wallheaven图片网站)

1. wallheaven 壁纸网站

这个网站的图片是提供下载的,在壁纸类别之中质量非常高,包括了很多的高清图片。 详细情况可访问其主页页面:wallheaven

2、分析网页架构

1)获取全部页面的地址分析 网页主页地址为:

https://wallhaven.cc/

输入关键词china进行查询后,地址变为:

https://wallhaven.cc/search?q=china

下滑到第二页之后,地址变为:

https://wallhaven.cc/search?q=china&page=2

那么我们就得到了一个通用的地址访问格式:

https://wallhaven.cc/search?q={}&page={}

其中两个中括号之中分别填写关键词和页数


2)获取全部图片的地质 查看一张图片的url地址

https://th.wallhaven.cc/small/mp/mp3dwm.jpg

但是点开图片再单独查看图片可见其地址为:

https://w.wallhaven.cc/full/mp/wallhaven-mp3dwm.jpg

对比前后两张图片,可以明显地发现首页展示的图片画质非常差,而且经过压缩之后大小变形了,用来做壁纸或者其他用途都很有限。所有我们通向希望得到详细页面中的高清页面。我们至此有两种方案可以获取得到图片的地址:

从首页进入图片页面,在图片页面获得图片下载地址从首页获得低清晰度图片下载地址,经过地址重组获得高清图片的下载地址

这里我选择第二种方法,以便捡一捡长时间不用的正则表达

3、编码实现

1) 导入相关函数库

import os import requests import redis from lxml import etree import urllib.request import time import threading from queue import Queue import re

2) 我后面打算使用redis作为中间件保存url等信息,暂时还没有使用,先定义好(可略过)

pool = redis.ConnectionPool(host='localhost',port=6379,decode_responses=True) r = redis.Redis(connection_pool=pool) print(r.ping())

3)主要函数及爬取过程 注意:

headers 中的内容根据自己的情况进行填写Producer类:获取全部的img地址consumer类:下载img我这里使用的关键词是’anime’,可以通过input来进行交互下载如果有什么错误或者认为不太正确的地方请联系我 Headers = { 'authority': 'wallhaven.cc', 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'cookie': '', # 请写上自己的 'referer': 'https://wallhaven.cc/', 'user-agent': '' # 请修改为自己的 } class Producer(threading.Thread): def __init__(self,page_queue,img_queue,*args,**kwargs): super(Producer, self).__init__(*args, **kwargs) self.page_queue = page_queue self.img_queue = img_queue def run(self): while True: if self.page_queue.empty(): break page_url = self.page_queue.get() page_text = self.deal_url(page_url) self.parse_indexPage(page_text) def deal_url(self,url): response = requests.get(url,headers=Headers) response.encoding= response.apparent_encoding return response.text def parse_indexPage(self,text): html = etree.HTML(text) wallpaper_urls = html.xpath("//img[@alt='loading']/@data-src") for url in wallpaper_urls: url = url.replace('th','w',1) # 替换第一个th为w url = url.replace('small','full') # 替换small为full last_urlTail = re.search(r'[^/]+(?!.*/)',url).group() #正则获取url最后一个/后的内容 new_urlTail = 'wallhaven-'+last_urlTail url = url.replace(last_urlTail,new_urlTail) #重构网址 self.img_queue.put((new_urlTail,url)) class Consumer(threading.Thread): def __init__(self,page_queue,img_queue,*args,**kwargs): super(Consumer,self).__init__(*args,**kwargs) self.page_queue = page_queue self.img_queue = img_queue def run(self): while True: if self.img_queue.empty() and self.page_queue.empty(): break img_name,img_url = self.img_queue.get() self.save_img(img_name,img_url) def save_img(self,img_name,img_url): root= './3_figure/' path = root+img_name try: if not os.path.exists(root): os.mkdir(root) if not os.path.exists(path): read_figure = requests.get(img_url) with open(path,'wb')as f: f.write(read_figure.content) f.close() print(path+" save ok!") else: print('文件已保存') except: print("文件爬取失败") def main(): base_url = 'https://wallhaven.cc/search?q={}&page={}' # keyword = input("please input the keyword") keyword = 'anime' page_queue = Queue(20) img_queue = Queue(200) page_num = 10 for x in range(1,page_num+1): url = base_url.format(keyword,x) page_queue.put(url) print(url) for x in range(5): t = Producer(page_queue,img_queue) t.start() for x in range(5): t = Consumer(page_queue,img_queue) t.start() if __name__ == '__main__': main()

4、结果视图

我下载了10页的图片,每页24张图片,共计240张: 打开其中的一张图片: 看起来画质还不错。

最新回复(0)