python项目实战——下载美女图片
文章目录
- python项目实战——下载美女图片
- 完整代码
- 思路整理
- 实现过程
- 使用xpath语法找图片的链接
- 检查链接是否正确
- 下载图片
- 创建文件夹
- 获取一组图片的链接
- 获取页数
- 获取目录页的链接
- 完善代码
- 注意事项
完整代码
import requests
import re
import pprint
from lxml import etree
import os# 拿到具体页面的链接下载一张图片
def download_images(url):rot = requests.get(url=url)rot.encoding=rot.apparent_encoding# print(rot.text)html = etree.HTML(rot.text)try:title = html.xpath('//div[@class="ImageBody"]//img/@alt')links = html.xpath('//div[@class="ImageBody"]//img/@src')# 显示下载内容# print(title[0])# print(links[0])number1 = html.xpath('//li[@class="thisclass"]/a[@href]/text()')# print(title[0]+str(number1[0]))# print(links[0])# 创建文件夹if not os.path.exists(f'图片/{title[0]}'):os.mkdir(f'图片/{title[0]}')pic = requests.get(url=links[0]).contentwith open(f'图片/{title[0]}/{title[0]}{str(number1[0])}.jpg','wb') as f:f.write(pic)print(f'已下载……{title[0]}{str(number1[0])}') # 提示下载成功except:print(f'出错了......{url}')# 给第一个图片的链接,就可以得到其他图片的链接
def link_of_pictures(url):rot = requests.get(url=url)# print(url) # 检查当前链接是否正确rot.encoding=rot.apparent_encoding# print(rot.text)html = etree.HTML(rot.text)features = re.findall('xingganmeinv/(\\d+).htm',url)[0]# print(features) # 这一组的特征值,比如http://www.umeituku.com/meinvtupian/xingganmeinv/208585.htm里面的208585# 获取页数numbers = html.xpath('//div[@class="NewPages"]//ul//li//a/text()')number = re.findall('共(\\d+)页',numbers[0])# print(number[0]) # 页数download_images(url)for i in range(2,int(number[0]) + 1):# 得到了这组图片的其他链接urll = re.sub(r'xingganmeinv/.*', f'xingganmeinv/{features}_{i}.htm', url)# print(urll)download_images(urll)# 得到这个系列的单页的链接
url = 'https://www.umeituku.com/meinvtupian/'
header = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0'}
rt = requests.get(url=url,headers=header)
rt.encoding = rt.apparent_encoding # apparent_encoding可以自己判断网页的编码方式,然后再传给encoding进行解析
# print(rt.text)
html = etree.HTML(rt.text)
title = html.xpath('//div[@class="TypeList"]//div[@class="ListTit"]/text()')
links = html.xpath('//div[@class="TypeList"]//a[@class="TypeBigPics"]/@href')
# pprint.pprint(title)
# pprint.pprint(links)
for item in links:link_of_pictures(str(item))
这个代码还能修改,但是作为掌握爬取网页图片来说,已经足够了
这里的第三个模块,是获取目录页的总链接,也就是第一页所有组的第一张,还能再次翻页,再次使用for循环就可以实现了
思路整理
- 获取图片页源代码
- 提取所有图片的链接
- 保存一组图片
- 爬取目录页源代码
- 下载图片
- 翻页下载
实现过程
首先是下载一张图片,这里最好是找个简单点的网址,不要去找太火的,有反爬机制,对于小白来说有点难
因为我折腾了好几天,提取的链接,就是不能独立下载
脑子突然开窍,换了个网站进度嗖嗖的
这里不推荐网站了,以免对网站造成干扰 想要可以去代码里面找
使用xpath语法找图片的链接
这里去看网页源代码,看看图片是否包含在源代码里面,如果在源代码里面,是最简单的情况
这里使用requests库的get请求,可以得到网页的源代码,找到了图片的位置,就是在源代码里面,如果不在源代码里面需要使用抓包的方式,获取图片的链接
检查链接是否正确
我们从源代码找到图片的链接之后,复制链接去浏览器查看,如果点开就是一张图片,那就成功了,如果不是就换网站
下载图片
我们将得到的图片链接再次给requests模块,保存图片的方式是二进制码流
pic = requests.get(url=links[0]).content
对,就是在requests函数后面再加一个content
就可以得到图片了,现在这个图片被我们保存在pic对象里面
再使用文件操作,就可以把图片保存在本地文件了
因为是二进制码流,我们在保存文件的时候使用wb的方式写入
with open(f'图片/{title[0]}/{title[0]}{str(number1[0])}.jpg','wb') as f:f.write(pic)print(f'已下载……{title[0]}{str(number1[0])}') # 提示下载成功
能下载图片之后,把上面这部分独立出来做成函数,让别的地方提供网址来使用
# 拿到具体页面的链接下载一张图片
def download_images(url):rot = requests.get(url=url)rot.encoding=rot.apparent_encoding# print(rot.text)html = etree.HTML(rot.text)try:title = html.xpath('//div[@class="ImageBody"]//img/@alt')links = html.xpath('//div[@class="ImageBody"]//img/@src')# 显示下载内容# print(title[0])# print(links[0])number1 = html.xpath('//li[@class="thisclass"]/a[@href]/text()')# print(title[0]+str(number1[0]))# print(links[0])# 创建文件夹if not os.path.exists(f'图片/{title[0]}'):os.mkdir(f'图片/{title[0]}')pic = requests.get(url=links[0]).contentwith open(f'图片/{title[0]}/{title[0]}{str(number1[0])}.jpg','wb') as f:f.write(pic)print(f'已下载……{title[0]}{str(number1[0])}') # 提示下载成功except:print(f'出错了......{url}')
这里我使用了try和except来进行异常捕获
因为在网站第四组图片的第10页是空图片,网址有效,但是没有找到图片
这里让程序进行一个报错,并显示出错的网址,就可以自己查看原因了
如下图所示,倘若不使用异常捕获,程序在这个报错的地方就会中断
一开始我还想少保存一张,比如最后一张不保存,那样就浪费数据了
创建文件夹
因为这里的图片都是一组一组的,所以采用创建文件夹的方式,把一组图片放在一个文件夹里面,这个文件夹里面放这一组图片,这个文件夹使用这组图片的标题命名,因为这组图片没有自己的名字,我们还需要人工加个序号
就像上图里面的某某1,某某2等等
使用os库创建文件夹,这个库可以获取程序运行的操作系统,根据不同的操作系统创建不同的文件夹
if not os.path.exists(f'图片/{title[0]}'):os.mkdir(f'图片/{title[0]}')
这里是使用if判断语句,判断文件夹是否存在,如果不存在,就使用os.mkdir创建一个
获取一组图片的链接
仔细检查一下,发现对于一组图片来说他们的网址有规律的变化
比如,meinvtupian/xingganmeinv/208585.htm
xingganmeinv/208585_2.htm
只有后面发生了变化
我们可以使用字符串替换函数,配合for循环生成这组图片的链接
# 给第一个图片的链接,就可以得到其他图片的链接
def link_of_pictures(url):rot = requests.get(url=url)# print(url) # 检查当前链接是否正确rot.encoding=rot.apparent_encoding# print(rot.text)html = etree.HTML(rot.text)features = re.findall('xingganmeinv/(\\d+).htm',url)[0]# print(features) # 这一组的特征值,比如http://www.umeituku.com/meinvtupian/xingganmeinv/208585.htm里面的208585# 获取页数numbers = html.xpath('//div[@class="NewPages"]//ul//li//a/text()')number = re.findall('共(\\d+)页',numbers[0])# print(number[0]) # 页数download_images(url)for i in range(2,int(number[0]) + 1):# 得到了这组图片的其他链接urll = re.sub(r'xingganmeinv/.*', f'xingganmeinv/{features}_{i}.htm', url)# print(urll)download_images(urll)
这里的features就是变化的地方,我管他叫特征值,你们可以随便起名字
获取页数
这里我们可以从源代码里面找到这一组图片的页数
然后根据页数生成链接,再让上面的函数去访问图片
错误示范:
一开始的时候发现,在图片的下面可以选择页数,点击第几页就会跳转,根据这个思路,好像可以把这个页数链接爬下来,制成列表再挨个访问
对于页数少的还可以,但是这个直接跳转只能最多显示7页,哪怕共10页,从第一页最多跳转到第7页
所以没办法直接从页面获取链接,只能根据规律自己改写链接
for i in range(2,int(number[0]) + 1):# 得到了这组图片的其他链接urll = re.sub(r'xingganmeinv/.*', f'xingganmeinv/{features}_{i}.htm', url)# print(urll)download_images(urll)
也就是得到页数,进行n次循环就好了
获取目录页的链接
从目录页可以看到多组图片的第一页,直接点击也可以完成跳转
检查源代码,发现每组图片的首页链接可以被爬取
# 得到这个系列的单页的链接
url = 'https://www.umeituku.com/meinvtupian/'
header = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0'}
rt = requests.get(url=url,headers=header)
rt.encoding = rt.apparent_encoding # apparent_encoding可以自己判断网页的编码方式,然后再传给encoding进行解析
# print(rt.text)
html = etree.HTML(rt.text)
title = html.xpath('//div[@class="TypeList"]//div[@class="ListTit"]/text()')
links = html.xpath('//div[@class="TypeList"]//a[@class="TypeBigPics"]/@href')
# pprint.pprint(title)
# pprint.pprint(links)
for item in links:link_of_pictures(str(item))
这里的url是目录页的链接
links是每组的首页链接列表
完善代码
这里的获取目录页链接还能再改,把这个操作改成函数,还能再写for循环,访问所有的目录页
貌似有成百上千个,这里作为代码展示就不写了,有能力的可以试试
注意事项
这段代码不能独立工作,必须放在项目里面
这个代码运行成功之后我就想做成exe程序,但是里面涉及了文件保存的地址,还有一些库函数
ai帮忙改了一下,让程序获取文件所在的位置,倒是解决了必须放在项目里面的问题,但是依旧不能打包exe或者文件夹
import requests
import re
import pprint
from lxml import etree
import os# 获取当前脚本的绝对路径
current_directory = os.path.dirname(os.path.abspath(__file__))
image_directory = os.path.join(current_directory, '图片')# 拿到具体页面的链接下载一张图片
def download_images(url):rot = requests.get(url=url)rot.encoding = rot.apparent_encodinghtml = etree.HTML(rot.text)try:title = html.xpath('//div[@class="ImageBody"]//img/@alt')links = html.xpath('//div[@class="ImageBody"]//img/@src')number1 = html.xpath('//li[@class="thisclass"]/a[@href]/text()') # 在这里提取 number1# 确保 title 和 number1 都有值if not title or not number1:print(f"未能提取标题或编号,URL: {url}")return# 创建文件夹image_folder = os.path.join(image_directory, title[0])if not os.path.exists(image_folder):os.makedirs(image_folder) # 使用 makedirs 可以创建多层目录pic = requests.get(url=links[0]).contentwith open(os.path.join(image_folder, f'{title[0]}{str(number1[0])}.jpg'), 'wb') as f:f.write(pic)print(f'已下载……{title[0]}{str(number1[0])}') # 提示下载成功except Exception as e:print(f'出错了......{url}, 错误信息: {e}')# 给第一个图片的链接,就可以得到其他图片的链接
def link_of_pictures(url):rot = requests.get(url=url)rot.encoding = rot.apparent_encodinghtml = etree.HTML(rot.text)features = re.findall('xingganmeinv/(\\d+).htm', url)[0]# 获取页数numbers = html.xpath('//div[@class="NewPages"]//ul//li//a/text()')number = re.findall('共(\\d+)页', numbers[0])download_images(url)for i in range(2, int(number[0]) + 1):urll = re.sub(r'xingganmeinv/.*', f'xingganmeinv/{features}_{i}.htm', url)download_images(urll)# 得到这个系列的单页的链接
url = 'https://www.umeituku.com/meinvtupian/'
header = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0'}
rt = requests.get(url=url, headers=header)
rt.encoding = rt.apparent_encoding
html = etree.HTML(rt.text)
title = html.xpath('//div[@class="TypeList"]//div[@class="ListTit"]/text()')
links = html.xpath('//div[@class="TypeList"]//a[@class="TypeBigPics"]/@href')for item in links:link_of_pictures(str(item))