前言

最近整理自己的项目时,发现之前自己写的爬取wallhaven网站顿时有来的兴趣决定再写一遍来回顾自己以前学的知识

网站地址:"https://wallhaven.cc/"

1. url参数结构

从url地址我们发现为"https://wallhaven.cc/search?categories=111&purity=110&sorting=date_added&order=desc&page=2",这段url里面代用几个参数分别为,categories,purit,sorting。而这几个参数分别对应界面的这几个按钮

2. 查看网页结构

按f12键查找到要爬取的图片目录



通过查看代码发现该图片只是一张预览图片,分辨率仅为300*200,明显不符合要求。

观察下方a标签



发现这个class为preview的标签中存在个href地址链接到该高清图片的正确地址,点击该地址跳转



通过查看代码发现这才是我们需要的图片,找到了我们要的图片链接,在img标签中。

通过以上观察我们可以知道,我们的代码编写思路

  1. 获取到这一页所有图片的url地址
  2. 通过解析获取到详情页网页的图片
  3. 请求到详情页网页图片进行下载

3. 开始爬取图片

3.1 初始化

import requests
url = "https://wallhaven.cc/search?categories=011&purity=010&sorting=date_added&order=desc&page=2"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36 Edg/88.0.705.56',
} class Spider:
# 初始化数据
def __init__(self, url, header, cookie):
self.user_url = url
self.header = header
self.img_list_url = [] # 存放一页的所有图片地址
self.num = 0 # 计数爬取了多少张图片

3.2 获取到这一页所有图片的url地址

我们在Spider类中定义一个res方法来爬取这一页的所有url地址,并且利用列表推导式将所有的url地址存放到list_img列表中以便我们后续使用

# 获取某一页要下载的图片所有链接
def res(self):
response = requests.get(self.user_url, headers=self.header).text
soup = BeautifulSoup(response, "html.parser")
img_href = soup.select(".thumb-listing-page > ul > li a[href]")
list_img = [i.get("href") for i in img_href] # 所有的图片的href
print(list_img)
print("一共", len(list_img), "图片")
return list_img

3.3 通过解析获取到详情页网页的图片

通过res方法我们得到了一页的所有图片链接,这时我们获取详情页的图片地址并把它存放到img_list_url列表中以便我们后续开启多进程进行下载。但是我们这些书写会出现拿不到详细页的图片地址从而导致下标越界从而报错,所以可以优化一下代码

# 获取详情页图片地址
def detail_page(self, list_img):
# 遍历获取详情页图片地址
for item in list_img:
detail_page = requests.get(item, headers=self.header, cookies=self.cookie).text
soup = BeautifulSoup(detail_page, "html.parser")
img_url = soup.select("#showcase > div.scrollbox > img[src]")[0]["src"]
self.img_list_url.append(img_url)
print(img_url, "添加成功")
self.error_img_url(item)
return self.img_list_url

可以写出这样

# 获取详情页图片地址
def detail_page(self, list_img):
# 遍历获取详情页图片地址
for item in list_img:
detail_page = requests.get(item, headers=self.header, cookies=self.cookie).text
soup = BeautifulSoup(detail_page, "html.parser")
try: # 访问过快会爬取不到详情页图片地址,则出现一个空列表从而导致下标越界
img_url = soup.select("#showcase > div.scrollbox > img[src]")[0]["src"]
self.img_list_url.append(img_url)
print(img_url, "添加成功")
except IndexError: # 出现下标越界调用error_img_url方法
self.error_img_url(item)
return self.img_list_url # 处理获取失败的图片地址
def error_img_url(self, url):
print(url, "没有获取到现在重新获取")
# 休眠2秒重新发送请求
time.sleep(2)
detail_page = requests.get(url, headers=self.header, cookies=self.cookie).text
soup = BeautifulSoup(detail_page, "html.parser")
try:
img_url = soup.select("#showcase > div.scrollbox > img[src]")[0]["src"]
self.img_list_url.append(img_url)
print(img_url, "获取成功")
except IndexError: # 如果还没有获取到图片地址那么递归调用
self.error_img_url(url)

3.4 请求到详情页网页图片进行下载

通过前面我们已经获取下载图片地址,我们发现地址为"https://w.wallhaven.cc/full/zy/wallhaven-zyg5kw.jpg "完全可以使用split('/')进行切片获取最后一段用来命名图片名称

# 图片下载
def download_images(self, img_url):
if img_url is not None:
img_name = img_url.split("/")[-1] # 图片名称
img = requests.get(img_url, headers=self.header).content
with open(img_path + "/" + img_name, "wb") as fp:
fp.write(img)
print(img_name, "download over~")
self.num += 1

3.5 main方法

这时候我们编写主函数就可以下载了

if __name__ == '__main__':
img_path = "./wall"
if not os.path.exists(img_path):
os.mkdir(img_path)
# 开始爬取
start = time.time()
spider = Spider(url, headers, cookie)
list_img = spider.res() img_list_url = spider.detail_page(list_img) # 开启5个进程下载图片
pool = Pool(5)
pool.map(spider.download_images, img_list_url) end = time.time()
print("下载图片数量:", Spider.images_count)
print(end - start)

4. 完整代码

import os
import time
from multiprocessing.dummy import Pool
import requests
from bs4 import BeautifulSoup url = "https://wallhaven.cc/search?categories=011&purity=010&sorting=date_added&order=desc&page=2"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36 Edg/88.0.705.56',
} class Spider:
# 初始化数据
def __init__(self, url, header, cookie):
self.user_url = url
self.header = header
self.cookie = cookie
self.img_list_url = [] # 存放一页的所有图片地址
self.num = 0 # 计数爬取了多少张图片 # 获取某一页要下载的图片所有链接
def res(self):
response = requests.get(self.user_url, headers=self.header).text
soup = BeautifulSoup(response, "html.parser")
img_href = soup.select(".thumb-listing-page > ul > li a[href]")
list_img = [i.get("href") for i in img_href] # 所有的图片的href
print(list_img)
print("一共", len(list_img), "图片")
return list_img # 获取详情页图片地址
def detail_page(self, list_img):
# 遍历获取详情页图片地址
for item in list_img:
detail_page = requests.get(item, headers=self.header).text
soup = BeautifulSoup(detail_page, "html.parser")
try: # 访问过快会爬取不到详情页图片地址,则出现一个空列表从而导致下标越界
img_url = soup.select("#showcase > div.scrollbox > img[src]")[0]["src"]
self.img_list_url.append(img_url)
print(img_url, "添加成功")
except IndexError: # 出现下标越界调用error_img_url方法
self.error_img_url(item)
return self.img_list_url # 处理获取失败的图片地址
def error_img_url(self, url):
print(url, "没有获取到现在重新获取")
# 休眠2秒重新发送请求
time.sleep(2)
detail_page = requests.get(url, headers=self.header).text
soup = BeautifulSoup(detail_page, "html.parser")
try:
img_url = soup.select("#showcase > div.scrollbox > img[src]")[0]["src"]
self.img_list_url.append(img_url)
print(img_url, "获取成功")
except IndexError: # 如果还没有获取到图片地址那么递归调用
self.error_img_url(url) # 图片下载
def download_images(self, img_url):
if img_url is not None:
img_name = img_url.split("/")[-1] # 图片名字
img = requests.get(img_url, headers=self.header).content
with open(img_path + "/" + img_name, "wb") as fp:
fp.write(img)
print(img_name, "download over~")
self.num += 1 def images_count(self):
print(self.num) if __name__ == '__main__':
img_path = "./wall"
if not os.path.exists(img_path):
os.mkdir(img_path)
# 开始爬取
start = time.time()
spider = Spider(url, headers, cookie)
list_img = spider.res() img_list_url = spider.detail_page(list_img) # 开启5个进程下载图片
pool = Pool(5)
pool.map(spider.download_images, img_list_url) end = time.time()
print("下载图片数量:", Spider.images_count)
print(end - start)

5. 添加Cookie

如果有wallhaven用户的想爬取用户能爬取的图片需要添加Cookie

# 用户cookie
cookie = {
"_pk_id.1.01b8": "xxxx",
"_pk_ses.1.01b8": "xxxx",
"remember_web_59ba36addc2b2f9401580f014c7f58ea4e30989d": "xxx",
"XSRF-TOKEN": "xxxx",
"wallhaven_session": "xxxx"
}

请求的时候带上cookie即可

多线程爬取wallhaven的更多相关文章

  1. Python爬虫入门教程 14-100 All IT eBooks多线程爬取

    All IT eBooks多线程爬取-写在前面 对一个爬虫爱好者来说,或多或少都有这么一点点的收集癖 ~ 发现好的图片,发现好的书籍,发现各种能存放在电脑上的东西,都喜欢把它批量的爬取下来. 然后放着 ...

  2. Python爬虫入门教程 13-100 斗图啦表情包多线程爬取

    斗图啦表情包多线程爬取-写在前面 今天在CSDN博客,发现好多人写爬虫都在爬取一个叫做斗图啦的网站,里面很多表情包,然后瞅了瞅,各种实现方式都有,今天我给你实现一个多线程版本的.关键技术点 aioht ...

  3. Python爬虫入门教程 11-100 行行网电子书多线程爬取

    行行网电子书多线程爬取-写在前面 最近想找几本电子书看看,就翻啊翻,然后呢,找到了一个 叫做 周读的网站 ,网站特别好,简单清爽,书籍很多,而且打开都是百度网盘可以直接下载,更新速度也还可以,于是乎, ...

  4. 实现多线程爬取数据并保存到mongodb

    多线程爬取二手房网页并将数据保存到mongodb的代码: import pymongo import threading import time from lxml import etree impo ...

  5. Python爬虫入门教程: All IT eBooks多线程爬取

    All IT eBooks多线程爬取-写在前面 对一个爬虫爱好者来说,或多或少都有这么一点点的收集癖 ~ 发现好的图片,发现好的书籍,发现各种能存放在电脑上的东西,都喜欢把它批量的爬取下来. 然后放着 ...

  6. Python3 多线程爬取梨视频

    多线程爬取梨视频 from threading import Thread import requests import re # 访问链接 def access_page(url): respons ...

  7. python多线程爬取斗图啦数据

    python多线程爬取斗图啦网的表情数据 使用到的技术点 requests请求库 re 正则表达式 pyquery解析库,python实现的jquery threading 线程 queue 队列 ' ...

  8. 使用selenium 多线程爬取爱奇艺电影信息

    使用selenium 多线程爬取爱奇艺电影信息 转载请注明出处. 爬取目标:每个电影的评分.名称.时长.主演.和类型 爬取思路: 源文件:(有注释) from selenium import webd ...

  9. python利用requests和threading模块,实现多线程爬取电影天堂最新电影信息。

    利用爬到的数据,基于Django搭建的一个最新电影信息网站: n1celll.xyz  (用的花生壳动态域名解析,服务器在自己的电脑上,纯属自娱自乐哈.) 今天想利用所学知识来爬取电影天堂所有最新电影 ...

随机推荐

  1. SQL语句——为什么分组函数(多行处理函数)不能用在where语句之后?

    在SQL语句中,常见的分组查询函数为: sum()求和 avg()求平均值 min()求最小值 max()求最大值 count()求数目 在分组函数中有几个重要的特征: 1.分组函数进行时自动忽略nu ...

  2. 痞子衡嵌入式:RT-MFB - 一种灵活的i.MXRT下多串行NOR Flash型号选择的量产方案

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是一种灵活的i.MXRT下多串行NOR Flash型号选择的量产方案. 对于以 i.MXRT 这类没有内部 NVM (Non-Volati ...

  3. Oracle安装和卸载

    Oracle安装: 1. 检查是否安装net framework 3.5 2. 安装win64_11gR2_database服务端 更改安装目录,设置密码 2. 检查服务 services.msc,两 ...

  4. Linux基础_5_文件管理

    创建 touch 文件名 #创建文件 stat 文件名 #查看文件属性 touch -am 文件名 #更改文件的访问时间及修改时间 删除 rm -rf s/* #递归强制删除s目录下的所有内容(包括文 ...

  5. jsp和java的结合使用显示学生信息

    package com.zyz; public class Student { private String ID; // 学号 private String name; // 姓名 private ...

  6. 9.pygame-键盘捕获

    创建英雄类 """英雄精灵""" class Hero(GameSprite): def __init__(self): # 调用父类方法, ...

  7. 教你如何解决T+0的问题

    摘要:T+0查询是指实时数据查询,数据查询统计时将涉及到最新产生的数据. 本文分享自华为云社区<大数据解决方案:解决T+0问题>,作者: 小虚竹 . T+0问题 T+0查询是指实时数据查询 ...

  8. CF Round #829 题解 (Div. 2)

    F 没看所以摆了 . 看拜月教教主 LHQ 在群里代打恰钱 /bx 目录 A. Technical Support (*800) B. Kevin and Permutation (*800) C. ...

  9. Java Timer使用介绍

    java.util包下提供了对定时任务的支持,涉及2个类: Timer:定时器类 TimerTask:任务抽象类 使用该定时任务我们需要继承TimerTask抽象类,覆盖run方法编写任务执行代码,并 ...

  10. packet Capture 手机抓包工具

    packet Capture packet Capture 是一款免root的app, 运行在安卓平台上,用于捕获http/https网络流量嗅探的应用程序 特点: 捕获网络数据包,并记录太慢,使用中 ...