【Python】无限制爬取Wallhaven壁纸网站源码&技术教学
本帖最后由 ARtcgb 于 2021-4-23 20:34 编辑# Python爬取(https://wallhaven.cc/)
之前看到论坛上已经有人发过这个壁纸站的爬虫,甚至还做了用户界面。所以我这个帖就不注重于代码了,而是注重于技术上面。
目标网址:wallhaven.cc
## 工具需求
第三方库:**requests BeautifulSoup**
展示操作环境:macOS Big Sur + Chrome + Python3.8
## 目标剖析 & 过程拆解
壁纸网站的爬虫和平常的爬虫其实没有什么区别,有些地方甚至还更简单。因为只要是你浏览器上显示的东西,爬虫都可以爬下来,壁纸网站的话就更好办了。
老规矩先看看F12,network刷新一下,看见img里面全是图片啊,这不就完事了?但是先观察一下,这些图片画质没有原图那么清晰,还不完整,都被切割成了300x200的缩略图。但是能发现,这些图片的名字有些奇怪,都是六位的字母+数字,回到HTML里面看一下,发现每个子页面的链接都是wallhaven.cc/w/ + 刚才缩略图的六位字母+数字构成的,还是传统的下载站布局。那就好说了。
wallhaven壁纸网站说白了还是个下载站的框架,和之前的套路一样,先从大的展示主页里面获取子页面的链接,再从子页面里面下载。这里下载图片需要用到写入文件的知识。
## 开始堆代码
观察下网页,我决定从toplist里面爬取壁纸,网站筛选菜单里有几个选项可以选,分别是General/Anime/People,生草翻译一下就是常规/二次元/三次元,看个人喜好自行选择;还有两个就是SFW/Sketchy,第一个就是safe for work,工作看很安全,嗯,那第二个就是工作时看**会出事**(确信
正常的toplist网址是这样的:https://wallhaven.cc/toplist
修改完几个选项之后就变成了这样:https://wallhaven.cc/search?categories=111&purity=110&topRange=1M&sorting=toplist&order=desc
但是把选项改回去和正常的选项一样,他的网址却回不去了:https://wallhaven.cc/search?categories=110&purity=100&topRange=1M&sorting=toplist&order=desc
这里面categories和purity的值发生了变化,多试几次发现分别和上面的几个选项有关。
|选项| categories| purity |
| ------- | -------- | -------- |
|General SFW| 100 | 100 |
|General Anime SFW| 110 | 100 |
|Anime SFW| 010 | 100 |
|Anime People SFW| 011 | 100 |
到这里可以确定categories每位都受一个前面的选项影响,选择就是1,不选择就是0。现在试一下purity。
|选项| categories| purity |
| ------- | -------- | -------- |
|General SFW| 100 | 100 |
|General Sketchy | 110 | 010 |
|General SFWSketchy| 100 | 110 |
写到这里我已经流鼻血了,网站链接就说这么多了,现在开始爬!
为了方便演示,源码中**出现**的网址为toplist的标准短链接形式,自定义爬虫时可替换,不会影响代码执行。
先request请求下来看看吧,这里用最普通的get请求就可以了,别忘了做个假的UA放到header里面。
```Python3
import requests
headers = {'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/4E423F'}
# 随便写的
html = "https://wallhaven.cc/toplist"
requests_html = requests.get(html, headers=headers)
print(requests_html.text)
```
HTML代码已经到手,很简单,现在该考虑解析了。F12里面看下我们需要的东西在哪里,不要被预览图所在的位置所迷惑,找到我们需要的链接在哪里就可以了。 `<a class="preview">`
拿出我们的老朋友BeautifulSoup,提取`<a class="preview">`的href值。
```Python3
Soup_all = BeautifulSoup(requests_html.text, 'lxml').find_all("a", class_="preview")
for Soup in Soup_all:
print(Soup['href'])
```
完事,换个方式把这些链接存到list里面,方便一会儿挨个爬取。
```Python3
url_list = []
for Soup in BeautifulSoup(requests_html.text, 'lxml').find_all("a", class_="preview"):
url_list.append(Soup['href'])
```
下面来看看单页。
更简单,图片链接直接在`<img id="wallpaper">`的src属性里面了,没有任何隐瞒。直接写代码。
```Python3
num = 0
for link in url_list:
requests_html = requests.get(link, headers=headers)
bs_html = BeautifulSoup(requests_html.text, "lxml")
img = bs_html.find('img', id='wallpaper')
r = requests.get(img['src'])
num += 1
with open("/Users/artcgb/Downloads/壁纸/+ str(num) + ".jpg", 'wb') as f:
f.write(r.content)
```
用上Python的读写文件操作,直接就可以写入图片,十分方便全程毫无尿点。缺点就是如果文件名一样,新鞋入的图片会覆盖之前的,所以我优化了下代码,让他每天爬的时候都新建一个文件夹存储,这样就不会覆盖掉了。
## 源代码
```Python3
import requests
from bs4 import BeautifulSoup
import os
import datetime
now = str(datetime.datetime.today().date())
# 获取当前日期
headers = {'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/4E423F'}
num = 0
url_list = []
for page in range(1, 6):
html1 = "https://wallhaven.cc/latest?page=" + str(page)
html2 = "https://wallhaven.cc/hot?page=" + str(page)
html_list =
for html in html_list:
requests_html = requests.get(html, headers=headers)
bs_html = BeautifulSoup(requests_html.text, "lxml")
for link in bs_html.find_all('a', class_="preview"):
image_link = link['href']
url_list.append(image_link)
num += 1
print("已获取第" + str(num) + "个链接")
a = os.path.exists("/Users/artcgb/Downloads/壁纸/" + now)
if a:
print("文件夹已存在,PASS")
else:
os.mkdir("/Users/artcgb/Downloads/壁纸/" + now)
print("文件夹建立成功")
# 建立文件夹存放图片
num = 0
for link in url_list:
requests_html = requests.get(link, headers=headers)
bs_html = BeautifulSoup(requests_html.text, "lxml")
img = bs_html.find('img', id='wallpaper')
r = requests.get(img['src'])
num += 1
with open("/Users/artcgb/Downloads/壁纸/" + now + "/" + str(num) + ".jpg", 'wb') as f:
f.write(r.content)
print("第" + str(num) + "张写入成功")
``` Wallhaven的精髓就是注册账号 点开NSFW专区 崇拜,一直没动力坚持学下来,鄙视自己! 太牛了,学习一下,感谢楼主分享的好东西 本帖最后由 Luckyu920 于 2021-4-23 17:31 编辑
open("/Users/artcgb/Downloads/壁纸/+ str(num)" + ".jpg", 'wb')
这个地方写错了
应该是
open("/Users/artcgb/Downloads/壁纸/" + str(num) + ".jpg", 'wb') Luckyu920 发表于 2021-4-23 17:26
open("/Users/artcgb/Downloads/壁纸/+ str(num)" + ".jpg", 'wb')
而且,忘记把now加进去了
最终应该是
open("/Users/artcgb/Downloads/壁纸/" + now + "/" + str(num) + ".jpg", 'wb') 感谢楼主分享的好东西 我这个运行之后报了个看不懂的错,我丢人了.... Luckyu920 发表于 2021-4-23 17:30
而且,忘记把now加进去了
最终应该是
对的,代码复制进来删了些东西,忘了复查一遍,谢谢{:1_907:} x827770484 发表于 2021-4-23 17:40
我这个运行之后报了个看不懂的错,我丢人了....
不知道啊,我没报过这样的错,看起来可能是因为请求太频繁被封IP了 爬的壁纸都会覆盖。。。不重命名始终只有一张
页:
[1]
2