今天不小心又发现了壁纸网站,感觉壁纸很多啊,多?我就忍不住了。爬一下咯。
我们今天爬取 网站是https://wallhaven.cc/。
先来分析分析:
进入首页:我们先去找标签,果然有个大标签地址链接。
点进去后发现:
一共有三层标签分类,第三层的标签就直接对应了很多的图片。
假如我们随便点击一个“anime girls”,我们发现他的标签号是5。
第一页呢只是几张图,但是有个按钮能看到更多,我们点进去。
发现url很有特点啊。q=tagId。我猜测这个q是query的意思。
后来经过测试,我们可以通过搜索自己输入的关键字,那时候q就是等于自己输入的关键字了。不过我们今天想从tag的角度来爬取网站。
往下翻一番,滑动下鼠标会发现,会出现page的分页标记。
%3A就是英文的冒号:。地址栏显示的时候就变成了%3A。
鼠标往下滑就是分页,而且在同一个页面展示,因此我们打开开发者模式的network去查看下XHR信息了。
好了,当我们确定;当我们得到个tagId,我们只需要去简单的添加page信息就可以得到完整的分页信息。
根据元素找到每一张图片,一般我们会先看到缩略图,点击缩略图后才能看到高清大图。
按照经验,一般而言,缩略图和高清图是存在某种直接的对应关系的,url存在规律的。
比如我们有缩略图:
所对应的高清图是:
再比如缩略图:
所对应的高清图是:
再比如缩略图:
所对应的高清图是:
发现确实存在规律哈
总结下就是得到如下规律:
好了分析完毕
完整代码如下:
import time
from concurrent.futures import ThreadPoolExecutor
import time
import os
import re
from urllib.parse import urlencode
import requests
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
rootrurl = 'https://wallhaven.cc/?'
searchUrl = 'https://wallhaven.cc/search?'
ImgUrl = 'https://w.wallhaven.cc/full/{}/wallhaven-{}'
save_dir = 'D:/estimages/'
headers = {
"Referer": rootrurl,
'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
'Accept-Language': 'en-US,en;q=0.8',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive'
} ###设置请求的头部,伪装成浏览器
def saveOneImg(dir, img_url):
new_headers = {
"Referer": img_url,
'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
'Accept-Language': 'en-US,en;q=0.8',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive'
} ###设置请求的头部,伪装成浏览器,实时换成新的 header 是为了防止403 http code问题,防止反盗链,
try:
img = requests.get(img_url, headers=new_headers) # 请求图片的实际URL
if (str(img).find('200') > 1):
with open(
'{}/{}.jpg'.format(dir, img_url.split('/')[-1].split('?')[0]), 'wb') as jpg: # 请求图片并写进去到本地文件
jpg.write(img.content)
print(img_url)
jpg.close()
return True
else:
return False
except Exception as e:
print('exception occurs: ' + img_url)
print(e)
return False
def processOnePages(tmpDir, imgs):
for img in imgs:
code = img.get('data-src').split('/')[-1]
# 拼装高清大图的地址
saveOneImg(tmpDir, ImgUrl.format(code[:2], code))
pass
def oneSpiderProcess(name, tag):
tmpDir = '{}/{}'.format(save_dir, name)
if not os.path.exists(tmpDir):
os.makedirs(tmpDir)
page = 1
while 1:
params = {
'q': tag,
'page' : page
}
url = searchUrl + urlencode(params)
print('current page is: %s' % url)
html = BeautifulSoup(requests.get(url, headers=headers).text, features="html.parser")
footer = html.find('footer', {'class': 'pagination-notice'})
if footer is not None:
break
imgs = html.find('section', {'class': 'thumb-listing-page'}).find('ul').find_all('img')
page = page + 1
processOnePages(tmpDir, imgs)
def getAllTags():
# 此处应该是从标签页面去获取很多的。为了演示,这里自己手动填写了几个演示一下
list = {'初音未来': 'id:3', '最终幻想VII': 'id:2659', 'Uzumaki Naruto': 'id:1188'}
return list
if __name__ == '__main__':
taglist = getAllTags()
# 给每个标签配备一个线程
with ThreadPoolExecutor(max_workers=5) as t: # 创建一个最大容纳数量为20的线程池
for name, tag in taglist.items():
t.submit(oneSpiderProcess, name, tag)
# test one tag
# oneSpiderProcess('初音未来', 'id:3')
# 等待所有线程都完成。
while 1:
print('-------------------')
time.sleep(1)
效果如下: