前言
我一个亲戚的小孩很喜欢二次元,也没事就喜欢画这些二次元的动漫人物,为了精进自己的技术,经常要在网上找自己喜欢的图片做参考,但是每次都很麻烦才能找到合适的图片,而且一次也只能保存一张,为了能有很多的图片素材做参考,他就找到了我,让我帮他家小孩搞一点这类的图片,这就有了今天这个案例。
今天这个案例就是爬取二次元的动漫图片,爬图片的案例之前也讲过不少,可是今天这个案例,看似很简单的网站,实则想找到真正的图片位置,确实一个很复杂的过程,话不多说,我们开始吧。
分析网页
如图分析所示,我们要的图片就在这个网址里面,但是这个网址里面只有很少的一部分图片,我们向下滚动网页,才能出现新的图片,这个很明显就是网站运用了Ajax技术,所以我们可以直接定位到xhr这个图标下。
在xhr图标下,经过我们的查找,定位到了,这个请求下,可以看出这里面才有关于图片的信息,但是这里经过我们查找,里面并没有这个图片的大图,这个里面只有图片的缩略图,我们要找的是图片的大图,所以就必须要进入到每个图片的链接里面去查找,虽然没有大图,但是不代表这里面就没有我们需要的信息,
可以看到,每张图片的链接都是有一个图片自己的id组成的,每个链接的不同,其实就是每张图片链接的id在变化,所以我们先请求出这些图片的链接,获取到每张图片的id,然后在构建每一个图片的链接地址,然后在请求这些地址,我们在进到图片地址里面看看
如图,可以看到,进入到图片链接里面并没有我们看到的图片,那么这图片在哪里呢,我们试着在这些请求里面找一下,加载图片的链接,
这才是真正加载图片的链接地址,那么这个链接地址到底在哪里呢,我们试着拿链接地址里面的一段数据搜索一下
可以很明显的看出包含链接地址的信息就是在主页的源码里面,
虽然在主页的源码里面,但是可以看出这里的标签是script,那也就代表这里面是一段js的代码,要想从这里面准确的找到我们能需要的数据,就需要先把它从js代码里面获取出来,然后在进一步的筛选,这里用到一个我之前介绍过的一个模块chompjs,它可以把看似像json的数据,把它转成真正的字典数据,从而方便我们的查找。剩下的就是找到真正图片的位置,然后给它清洗出来。
现在说一下大体思路,我们先通过api接口拿到每张图片的id,然后把这些id构建成图片的链接地址,请求这些链接地址,获取到每个链接地址的源码信息,通过正则把需要的信息从js代码里面匹配出来,然后通过chompjs这个模块把数据转换成字典数据,从字典数据中筛选出我们要的图片真实地址,最后保存。
案例模块
import httpx
import chompjs
import json
import fuckit
import re
import os
from faker import Faker
构建url列表,然后对url发送请求,获取响应数据
def get_url_list():
"""构建url列表
Returns:
_type_: _description_
"""
return [page_url.format(i) for i in range(1, 2)]
def parse_url(url):
"""发送请求,获取响应数据
Args:
url (_type_): _description_
Returns:
_type_: _description_
"""
with httpx.Client() as s:
r = s.get(url, headers=headers)
return r.content.decode()
提取每张图片的id数据
def get_img_ids(json_str):
"""提取出每张图片的id
Args:
json_str (_type_): _description_
Yields:
_type_: _description_
"""
json_datas = json.loads(json_str)
for json_data in json_datas.get('data').get('top_list_item_info'):
# 提取图片id
yield {'img_id': json_data.get('item_detail').get('item_id')}
提取图片的真实地址
def get_pic_url(html_str):
"""获取图片的真实url地址
Args:
html_str (_type_): _description_
Returns:
_type_: _description_
"""
pattern = 'window.__ssr_data = JSON.parse\("(.*?)"\);'
with fuckit:
json_str = re.search(pattern, html_str, re.S).group(1).replace('\\', '')
json_data = chompjs.parse_js_object(json_str)
img_url_temp = json_data.get('detail').get('post_data').get('multi')[0].get('origin')
pic_url = re.sub('u002F', '/', img_url_temp)
return pic_url
保存图片
def down_pic(pic_url):
"""保存图片
Args:
pic_url (_type_): _description_
"""
f = Faker(locale='zh_CN')
pic_name = f.random_number(digits=8)
path = os.path.join('cos_img', f'{pic_name}.jpg')
r = httpx.get(pic_url, headers=headers)
with open(path, 'wb') as f:
f.write(r.content)
print(f'{pic_name}爬取成功......!!!')
实现程序的主要逻辑思路
def main():
"""实现程序的主要逻辑思路
"""
# 1.构建url列表
url_list = get_url_list()
for url in url_list:
# 2.发送请求,获取响应数据
json_str = parse_url(url)
# 3.提取图片id
img_ids = get_img_ids(json_str)
for img_id in img_ids:
# 4.构建图片的链接地址
img_url = img_url_temp.format(img_id.get('img_id'))
# 5.对图片链接发送请求
html_str = parse_url(img_url)
# 6.提取图片真实的地址
pic_url = get_pic_url(html_str)
# 7.保存图片
down_pic(pic_url)
效果展示
案例具体步骤可以看我b站,里面有本案例具体步骤。
b站账号:
https://space.bilibili.com/351138764