Python编程实现:如何获取二次元女友并转换为PNG格式图片
[id_265996830]
[id_1124288453]
我有个朋友最近特别沉迷二次元,他渴望能与喜欢的二次元角色相伴一生,就如同 11 区那个与初音未来结婚的阿宅一样。我作为朋友,决定为他的人生增添一些别样的色彩,让他深陷二次元无法自拔。于是,我在二次元的世界里,用 Python 帮他找到了二次元女友(们)。
二次元是人类幻想出来的唯美世界,但其本质是我们心中对梦想生活的憧憬和对美好未来的期望,这种卡哇伊的颜,让人喜爱,我给你讲。
程序说明
从知名二次元网站触站进行爬取,从而获取到高清动漫图片,接着把获取到的 webp 格式图片转化成更为常见的 png 格式图片。
二次元女友获取程序
使用 requests 库来请求网页的内容,接着使用 BeautifulSoup4 对网页进行解析,最后运用 PIL 库把 webp 格式的图片转换为更为普遍的 png 格式图片。
观察网页结构
首先选择想要获取的图片类型。这里以女孩子为例,不过大家也可以选择生活类的图片,或者选择脚掌类的图片,甚至可以选择男孩子类的图片。
进入女孩子的标签页面,接着观察该页面的链接,然后爬取多个页面,查看发现第 2 页的链接是:
https:在 www.huashi6.com/tags/161 这个网址中,参数 p 的值为 2。
第3页链接为:
https:在 www.huashi6.com/tags/161 这个网址下,当前页码为 3。
从所给内容能够看出,不同页面的网址只是对页面数字进行了改变。基于此,可以构建出如下的模式,并且通过使用循环来爬取所有的页面。
url_pattern = 该链接为 https://www.huashi6.com/tags/161 ,并且后面带有参数 {} 。
for i in range(1, 20):
url = url_pattern.format(i)
在爬取网页之前,先使用浏览器的“开发者工具”来观察网页结构。接着首先去尝试定位图片元素。
于是自然而然地就想到了运用 find_all 语法来获取所有具有 class=‘v-lazy-img v-lazy-image-loaded’这种属性的标签。
img_url = soup.find_all('img', attr={'class': "v-lazy-img 以及 v-lazy-image-loaded"})
但是没有成功获取到。接着经过进一步的探索后发现,它的图片信息是在 script 元素里以动态的方式进行加载的。
需要注意的是,在请求页面时,能够在构造请求头时添加“Cookie”键值。并且,即便没有此键值,也可以让程序运行。
headers = {
User-Agent 为 Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:86.0) Gecko/20100101 Firefox/86.0 。此 User-Agent 表明使用的是 Firefox 86.0 浏览器,系统为 Ubuntu 且基于 Linux x86_64 架构,其版本号为 86.0 ,同时还包含 Gecko 引擎及特定的标识信息。
# 根据自己的情况修改Cookie值
#'Cookie':''
}
url_pattern = 该链接为 https://www.huashi6.com/tags/161 。
使用 requests 库发送一个 GET 请求,请求的 URL 为指定的 url,请求头为指定的 headers,将返回的响应赋值给 response
页面解析
使用 beautifulsoup 来解析页面,从而获取 JS 里所需要的数据。
results = soup.find_all('script')[1]
为了能够使用re解析获取内容,需要将内容转换为字符串:
image_dirty = str(results)
接下来构造正则表达式获取图片地址:
pattern使用 item 和 re.I|re.M 来编译正则表达式,即 re.compile(item, re.I|re.M)
然后查找所有的图片地址:
result_listpattern 会在 image_dirty 中进行查找并找出所有匹配的内容。
为了方便获取所需字段,构造解析函数
def analysis(item,results):
pattern = re.compile(item, re.I|re.M)
result_list = pattern.findall(results)
return result_list
打印获取的图片地址:
urls = analysis(r'"path":"(.*?)"', image_dirty)
urls[0:1]
发现一堆奇怪的字符:
'images/resource/2021/06/20/906h89635p0.jpg' 这个路径所指向的文件是一个图片文件,它位于特定的资源目录中,具体的时间信息为 2021 年 6 月 20 日,文件编号为 906h89635p0。,
这是因为网页编码的缘故。一开始用 utf-8 方式去解码网页,然而这种方式并不能解码 Unicode。
response.encoding = 'utf-8'
response.raise_for_status()
soup 等于使用 BeautifulSoup 对 response.text 进行处理,具体来说,就是以 response.text 作为输入,通过 BeautifulSoup 来解析和处理它,从而得到 soup 这个对象。'html.parser')
因此虽然可以通过以下方式获取原始地址:
url = 该文件路径为 images 文件夹下的 resource 文件夹中 2021 年 5 月 22 日的 90h013034p0.jpg
decodeunichars = url.encode('utf-8').decode('unicode-escape')
我们可以通过 response.encoding = 'unicode-escape' 来进行较为简单的解码。这种方式的缺点是,网页中的许多中文字符会变成乱码。不过,字本身并不是最重要的,不是吗?来看图吧!
创建图片保存路径
为了下载图片,首先创建图片保存路径:
# 创建图片保存路径
if not os.path.exists(webp_file):
os 会创建 webp_file 目录,如果该目录已存在则不会报错。exist_ok 这个参数用于控制这种行为。如果设置为 True,当目录已存在时不会引发异常;如果设置为 False,当目录已存在时会引发 FileExistsError 异常。True)
if not os.path.exists(png_file):
os 会创建指定的目录 png_file ,如果该目录已经存在,且 exist_ok 参数被设置为 True ,则不会引发异常;如果该目录不存在,则会创建该目录。True)
图片下载
当使用另存为选项时,我们发现格式是 webp。然而,之前获取的图片地址是 jpg 或者 png。如果直接将其存储为 jpg 或 png 格式,就会引发格式错误。
因此需要重新构建webp格式的文件名:
name = img.split('/')[-1]
name = name.split('.')[0]
name_webp = name + '.webp'
获取的图片地址不完整,所以需要添加网站主页来构建图片地址。
从 urllib.request 中导入 urljoin 这个函数。
该语言的风格要求将原文进行改写,避免使用原文用过的词语,对句子结构和用词进行调整、充实,力求差异最大化且保留原意,禁止修改专有名词,禁止穿插英文单词,只需改写结果。原句为“domain = 'https://img2.huashi6.com'”,改写后的句子为:此语言风格规定需对给定内容进行改写,要避免使用原句中的词语,对句子结构和用词进行调整与充实,以达到差异最大化的效果,同时要保留原意,并且不能修改专有名词,也不能穿插英文单词,仅需给出改写结果。
img_url = urljoin(domain,img)
接下来就是下载图片了:
r = requests.get(img_url,headers=headers)
if r.status_code == 200:
with open(name_webp, 'wb') as f:
f.write(r.content)
格式转换
最后,得到的图片是 webp 格式。如果想要得到更为常见的 png 格式,那就需要借助 PIL 库来进行转换。
打开名为 name_webp 的文件,将其作为图像进行读取,得到的图像对象赋值给 image_wepb 。
image_wepb.save(name_png)
爬取结果展示
完整程序
import time
import requests
from bs4 import BeautifulSoup
import os
import re
from urllib.request import urljoin
from PIL import Image
webp_file = 'girlfriends_webp'
png_file = 'girlfriends_png'
print(os.getcwd())
# 创建图片保存路径
if not os.path.exists(webp_file):
os.makedirs(webp_file, exist_ok=True)
if not os.path.exists(png_file):
os 会创建指定的目录 png_file ,如果该目录已经存在,那么不会引发错误,而是直接忽略。也就是说,即使 png_file 所指定的目录已经存在,os.makedirs 函数也不会报错,而是会继续执行后续的代码。True)
headers = {
'User-Agent':Mozilla/5.0 ,其运行环境为 X11 ,系统是 Ubuntu ,架构是 Linux x86_64 ,版本号为 rv:86.0 ,使用的引擎是 Gecko/20100101 ,浏览器名称是 Firefox/86.0,
#'Cookie':''
'Connection': 'keep-alive'
}
url_pattern = "https://www.huashi6.com/tags/161?p={}"
domain = 'https://img2.huashi6.com'
# 图片地址获取函数
def analysis(item,results):
使用 re.compile 函数创建一个正则表达式模式对象,其中的 item 作为要匹配的模式,re.I 和 re.M 是标志位,用于控制正则表达式的匹配方式,分别表示忽略大小写和多行匹配。
使用 pattern 在 results 中进行查找并获取到结果列表 result_list 。
return result_list
# 图片格式转换函数
def change_webp2png(name_webp 以及 name_png 还有 img_url):
try:
使用 Image.open 函数打开名为 name_webp 的文件,并将其赋值给 image_wepb 变量。
image_wepb.save(name_png)
except:
下载名为 name_webp 的图像和名为 name_png 的图像,图像的网址为 img_url。
# 图片下载函数
def download_image(name_webp, name_png, img_url):
if not os.path.exists(name_png):
if os.path.exists(name_webp):
os.remove(name_webp)
print(img_url)
使用 requests 库发送 GET 请求获取 img_url 的内容,并且设置了请求头 headers 。具体来说,通过 r = requests.get(img_url,headers=headers) 这行代码来实现该功能。
# print(r.content)
time.sleep(5)
if r.status_code == 200:
with open(name_webp, 'wb') as f:
f.write(r.content)
调用 change_webp2png 函数,传入 name_webp 和 name_png 作为参数,同时传入 img_url 作为另一个参数。
for i in range(1, 20):
time.sleep(5)
url = url_pattern.format(i)
使用 requests 库发送一个 GET 请求,请求的地址是 url ,请求头是 headers ,将返回的响应赋值给 response 。
# 解码
# response.encoding = 'utf-8'
response.encoding = 'unicode-escape'
response.raise_for_status()
soup 等于使用 BeautifulSoup 对 response.text 进行处理,其处理方式为传入 response.text 作为参数,同时可能还有其他相关操作或参数设置(但原文未明确提及其他相关内容)。'html.parser')
results = soup.find_all('script')
image_dirty = str(results[1])
urls = analysis(r'"path":"(.*?)"', image_dirty)[:20]
for img in urls:
img_url = urljoin(domain,img)
# 获取文件名
name = img.split('/')[-1]
name = name.split('.')[0]
name_webp = name + '.webp'
name_webp 是将 webp_file 和 name_webp 进行拼接得到的路径,即 name_webp 等于 os.path.join(webp_file, name_webp) 。
name_png = name + '.png'
name_png 是由 png_file 和 name_png 拼接而成的路径
下载名为 name_webp 的图片和名为 name_png 的图片,其图片地址为 img_url。
球点赞
文章评论