多线程爬虫!再也不用担心没有壁纸用了!
本帖最后由 Allen丶咩 于 2020-5-28 06:05 编辑# 多线程下载高清壁纸
- 平台 macOS
- python版本 3.7
- 第三方库 requests, lxml, unipath
- 多线程, 生产者消费者模式
- 采用 xpath 解析网页数据
- 支持选取分类
- 支持下载指定数量的图片
http://47.240.52.47:8000/640x400.gif
论坛小萌新第一次发帖, 如有错误请多多指教!
这几天逛论坛看到了@[一只码农](https://www.52pojie.cn/home.php?mod=space&uid=1215951)的帖子 (https://www.52pojie.cn/forum.php?mod=viewthread&tid=1162877&extra=page%3D1%26filter%3Dtypeid%26typeid%3D29) 突然就想要模仿写一个, 代码里面有很多东西都是借鉴了码农大神, 希望代码有疏漏的地方还请各位大神指出并提出意见!
再次感谢大佬提供的思路
代码直接贴在下面了, 运行不了就把第三方库安装一下
由于我用的MAC代码出来以后也没有在Windows平台测试, 可能存在的问题有:
1. 文件夹无法自动创建
2. 文件夹创建时的路径不对
如果遇到什么bug还请各位大佬提出来, 代码不足的地方也请多多赐教!!
*运行界面*
*文件夹*
*代码*
```
#!/usr/local/bin/python3
# -*- coding: UTF-8 –*-
import requests
import threading
from lxml import etree
from queue import Queue
from unipath import Path
import logging
import time
import os
import random
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s', datefmt='%H:%M:%S')# 配置日志
class SpiderWP():
def __init__(self):
self.num = 10# 爬取图片的张数
self.queue = Queue()# 队列
self.BASE_URL = "http://www.netbian.com/"# 网址
self.sort = {}# 分类对应的链接
self.file_path = Path(Path(__file__).parent, '壁纸')# 创建的壁纸路径
self.sort_flag = ''# 分类标记
# 请求并返回Element
def req(self, _url):
rs = requests.get(_url).content.decode("gbk")
html = etree.HTML(rs)
return html
# 获取分类
def get_sort(self):
html = self.req(self.BASE_URL)
tags = html.xpath("//div[@class='nav cate']/a")
for tag in tags:
self.sort = self.BASE_URL + tag.get("href")
# 递归生成图片的入口链接
def get_page(self, _url):
while True:
html = self.req(_url)
tags = html.xpath("//div[@class='wrap clearfix']//li/a")
for tag in tags:
self.get_jpg(self.BASE_URL + tag.get('href'))
try:
next_link = self.BASE_URL + \
html.xpath("//a/@href")
except IndexError:
logging.warning('图片已全部下载')
self.num = 0
if self.num != 0:
self.get_page(next_link)
else:
break
# 获取图片链接添加队列
def get_jpg(self, _url):
if self.num != 0:
html = self.req(_url)
try:
title = html.xpath("//div[@class='action']//h1/text()")
link = html.xpath("//div[@class='pic']//p//a//img/@src")
self.queue.put((title, link))
self.num -= 1
except IndexError:
logging.warning("图片解析失败,跳过...")
# 下载图片
def download(self):
while True:
if not self.queue.empty():
title, link = self.queue.get()
# 下载图片间隔时间,不建议太低给服务器造成压力(多线程下载的已经很快了)
time.sleep(2)
jpg = requests.get(link).content
title = title + '.' + link.split(".")[-1]
jpg_path = Path(self.jpg_path, title)
# 如果本地已经存在同名文件,随机改名
if jpg_path.exists():
jpg_path = Path(self.jpg_path, title.split('.') + str(random.randint(1, 100)) + '.' + link.split(".")[-1])
logging.info('下载:%s', title)
with open(jpg_path, 'wb') as f:
f.write(jpg)
# 如果队列为空,则结束程序
if self.num == 0 and self.queue.empty():
logging.info('下载完成')
break
def mean(self):
print('''日历 动漫 风景 美女 游戏 影视 动态 唯美 设计 护眼
可爱 汽车 花卉 动物 节日 人物 美食 水果 建筑 体育
军事 非主流 其他 LOL王者荣耀
-------------------------请输入分类名称-------------------------''')
while True:
inp = input("==>")
if inp in self.sort:
# 根据输入分类在‘壁纸’文件夹下创建子文件夹
self.jpg_path = Path(self.file_path, inp)
if not self.jpg_path.exists():
os.makedirs(self.jpg_path)
self.sort_flag = inp
#
while True:
try:
self.num = int(
input('-------------------------请输入下载张数-------------------------\n==>'))
break
except ValueError:
print('请输入数字')
break
else:
print('输入有误,请重新输入')
def run(self):
self.get_sort()
self.mean()
r = threading.Thread(target=self.get_page, args=((self.sort,)))
r.start()
# 多进程开启,不建议调高
for i in range(8):
t = threading.Thread(target=self.download)
t.start()
a = SpiderWP()
a.run()
``` fanvalen 发表于 2020-5-27 23:41
所以get要(timeout=**)
谢谢大佬, 想了好久怎么处理结束的问题, 后来是用判断剩余图片量(self.num)和判断队列是否为空来跳出循环的 hj170520 发表于 2020-5-27 23:52
大体看完,都理解的。谢谢楼主
我额外又复习了一遍。
logging 这个包我还第一次看到,哈哈哈
日志调试的包, 也可以以文件的形式输出到本地 前排顶贴! 没看懂这爬虫的意义。。。是网站不给下载。还是不给预览? 是高清原图吗??? geniusrot 发表于 2020-5-27 22:26
没看懂这爬虫的意义。。。是网站不给下载。还是不给预览?
重点是批量 diyikuai 发表于 2020-5-27 22:26
是高清原图吗???
1080x1920的
[url=forum.php?mod=redirect
我也刚接触Python,说实话,应用有局限性。 还不如爬微软的壁纸。我还挺喜欢看微软的壁纸的。 多线程要处理超时的问题,不然其中一个卡主,你的程序没法结束 如楼上所说,多线程是个问题{:1_926:}
虽然一般可能不会有啥事
页:
[1]
2