需求:1.至少要保存1000张图片2.不能出现重复的图片3.保存的图片文件名要以网站中所给的图片名命名4.请以面向对象的方式实现5.所有的图片请单独存放在同一个文件夹中
第一页网址:https://pic.netbian.com/index.html
第二页网址:https://pic.netbian.com/index_2.html
第三页网址:https://pic.netbian.com/index_3.html
观测每一页的网址发现除了第一页index后不带数字,其他页面index后面的数字都是对应的页码
class BiAn(object):
def init(self):
# 获取二级网址
def get_href(self):
# 获取图片网址
def get_img_url(self, title, href):
# 对所有图片详细网址并发请求的方法
def concurrency(self):
# 需要并发的请求方法
async def requests(self, title, img_url):
# 保存图片的方法
def save_img(self, title, content):
# trunc方法
def trunc(self):
# 当前文件夹如果没有picture文件夹,就创建picture文件夹
if not os.path.exists('./picture'):
os.mkdir('./picture')
# 收集所有的图片信息,这里为图片名和图片网址
self.img_info = []
# 输入需要爬取的页数
self.page = int(input('请输入需要爬取的页数:'))
# 彼岸网址,需要个请求头就行
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
}
for i in range(1, self.page+1):
# 第一页的网址区别于其他页,直接if判断
if i == 1:
url = 'https://pic.netbian.com/index.html'
else:
url = f'https://pic.netbian.com/index_{i}.html'
# 对一级网址发起请求
response = requests.get(url=url, headers=self.headers).text.encode('iso-8859-1').decode('gbk')
# 使用etree解析目标网址
tree = etree.HTML(response)
# 获取图片列表信息
li_list = tree.xpath('//div[@id="main"]/div[3]/ul/li')
# 遍历图片列表信息
for li in li_list:
# 获取单张图片名称 有些页面title在b标签下的便签里,所以要用//
title = li.xpath('./a/b//text()')[0]
# 获取图片二级网址地址
href = 'http://pic.netbian.com' + li.xpath('./a/@href')[0]
# 调用get_img_url
self.get_img_url(title, href)
# 对二级网址发起请求
response = requests.get(url=href, headers=self.headers).text
# 使用etree解析目标网址
tree = etree.HTML(response)
# 获取图片详细网址,获取到的网址不全需要拼接
img_url = 'http://pic.netbian.com' + tree.xpath('//*[@id="img"]/img/@src')[0]
# 将名称和网址封装在一个字典中
item = {
'title': title,
'url': img_url
}
# 图片的信息添加到列表中
self.img_info.append(item)
def concurrency(self):
# 定义一个任务列表
stasks = []
# 遍历所有的图片网址
for url in self.img_info:
# 调用requests方法
c = self.requests(url['title'], url['url'])
# 封装任务
task = asyncio.ensure_future(c)
# 添加到任务列表
stasks.append(task)
# 创建一个协程任务对象
loop = asyncio.get_event_loop()
# 将任务列表封装到wait中
loop.run_until_complete(asyncio.wait(stasks))
# 需要并发的请求方法
async def requests(self, title, img_url):
# 请求图片网址获取二进制数据
content = requests.get(url=img_url, headers=self.headers).content
# 调用save_img方法用于保存图片
self.save_img(title, content)
def save_img(self, title, content):
# 以二进制的方式打开一个jpg文件
with open(f'./picture/{title}.jpg', 'wb')as fp:
# 将二进制数据写入打开的jpg文件
fp.write(content)
# 关闭文件
fp.close()
# 输出提示信息
print(f'{title}下载完成')
,解决方法
response = requests.get(url=url, headers=self.headers).text.encode('iso-8859-1').decode('gbk')
href = 'http://pic.netbian.com' + li.xpath('./a/@href')[0]
img_url = 'http://pic.netbian.com' + tree.xpath('//*[@id="img"]/img/@src')[0]
# 定义一个爬虫类
class BiAn(object):
def __init__(self):
# 当前文件夹如果没有picture文件夹,就创建picture文件夹
if not os.path.exists('./picture'):
os.mkdir('./picture')
# 收集所有的图片信息,这里为图片名和图片网址
self.img_info = []
# 输入需要爬取的页数
self.page = int(input('请输入需要爬取的页数:'))
# 彼岸网址,需请求头,最好把cookie加上
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
}
# 获取图片子网址的方法
def get_href(self):
# 遍历每一页网址
for i in range(1, self.page+1):
# 提示信息
print(f'正在获取第{i}页的信息。。。')
# f格式化网址
if i == 1:
url = 'https://pic.netbian.com/index.html'
else:
url = f'https://pic.netbian.com/index_{i}.html'
# 对一级网址发起请求
response = requests.get(url=url, headers=self.headers).text.encode('iso-8859-1').decode('gbk')
print(response)
# 使用etree解析目标网址
tree = etree.HTML(response)
# 获取图片列表信息
li_list = tree.xpath('//div[@id="main"]/div[3]/ul/li')
# 遍历图片列表信息
for li in li_list:
# 获取单张图片名称
title = li.xpath('./a/b/text()')[0]
# 获取图片二级网址地址
href = 'http://pic.netbian.com' + li.xpath('./a/@href')[0]
# 调用get_img_url
self.get_img_url(title, href)
# 从二级网址获取图片详细网址
def get_img_url(self, title, href):
# 对二级网址发起请求
response = requests.get(url=href, headers=self.headers).text
# 使用etree解析目标网址
tree = etree.HTML(response)
# 获取图片详细网址,获取到的网址不全需要拼接
img_url = 'http://pic.netbian.com' + tree.xpath('//*[@id="img"]/img/@src')[0]
# 将名称和网址封装在一个字典中
item = {
'title': title,
'url': img_url
}
# 图片的信息添加到列表中
self.img_info.append(item)
# 对所有图片详细网址并发请求的方法
def concurrency(self):
# 定义一个任务列表
stasks = []
# 遍历所有的图片网址
for url in self.img_info:
# 调用requests方法
c = self.requests(url['title'], url['url'])
# 封装任务
task = asyncio.ensure_future(c)
# 添加到任务列表
stasks.append(task)
# 创建一个协程任务对象
loop = asyncio.get_event_loop()
# 将任务列表封装到wait中
loop.run_until_complete(asyncio.wait(stasks))
# 需要并发的请求方法
async def requests(self, title, img_url):
# 请求图片网址获取二进制数据
content = requests.get(url=img_url, headers=self.headers).content
# 调用save_img方法用于保存图片
self.save_img(title, content)
# 保存图片的方法
def save_img(self, title, content):
# 以二进制的方式打开一个jpg文件
with open(f'./picture/{title}.jpg', 'wb')as fp:
# 将二进制数据写入打开的jpg文件
fp.write(content)
# 关闭文件
fp.close()
# 输出提示信息
print(f'{title}下载完成')
# __trunc__方法
def __trunc__(self):
self.get_href()
# 实例化一个BiAn类的对象
bian = BiAn()
# 计时器,开始时间点
star_tiem = time.time()
# 调用__trunc__方法程序执行,获取到图片信息,并存储在self.img_info里
bian.__trunc__()
# 调用concurrency方法来实现并发,节省运行时间
bian.concurrency()
# 看一下程序运行用了多长时间
print(time.time()-star_tiem)
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!