level 1
hn三七情
楼主
需求:1.至少要保存1000张图片 2.不能出现重复的图片3.保存的图片文件名要以网站中所给的图片名命名4.请以面向对象的方式实现5.所有的图片请单独存放在同一个文件夹中

(一)分析目标网址1.目标网页每页20张图片,需要获取1000张图片则需要翻页
第一页网址:https://pic.netbian.com/index.html
第二页网址:https://pic.netbian.com/index_2.html
第三页网址:https://pic.netbian.com/index_3.html
观测每一页的网址发现除了第一页index后不带数字,其他页面index后面的数字都是对应的页码
2.不能出现相同的图片,这里使用图片名称来判断,如果图片名称一样,则判断图片一样,不重复下载。3.网页中开发目标网址,获取图片名称4.使用python创建一个面向目标网址的类,及写入获取目标图片的方法5.使用os库来创建一个文件夹
(二)获取目标位置1.在网页地址栏输入目标网址,打开网页;2.按下F12打开开发者工具,下图中红色部分;

3.鼠标点击资源定位符

然后点击需要定位的图片,如

定位到目标位置

在这就可以获取到图片网址(src,注意网址不全需要拼接)和名称(<b>标签里),通过xpath就可以提取出来;
4.通过下载发现用src下载的图片分辨率比较小

5.点击

进入目标图片的二级目录,并按F12打开开发者工具,资源定位符点击目标图片

,发现二级目录下也有个src,且与一级目录的不一样;6.点击

进入图片的三级目录,发现是我们需要的图片网址。

(三)python代码实现1.定义一个爬虫类,及方法
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):
2. init# 当前文件夹如果没有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'
}3.获取所有图片的二级目录网址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)4.获取图片的三级目录网址(及分辨率较高的图片网址)# 对二级网址发起请求
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)5.并发及一级获取图片二进制数据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)6.保存图片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}下载完成')(四)小tips1.第一页的网址并不是https://pic.netbian.com/index_1.html,而是https://pic.netbian.com/index.html,所以第一页要特殊处理,使用if判断,如果是第一页,直接定义url='https://pic.netbian.com/index.html',其他页码就用f格式化;2.获取图片名称时不能再a标签里@title提取

,因为第二页a便签就没有title属性了,会获取不到图片名称而要在a标签的b便签下获取 文本属性

3.获取图片名称时response = requests.get(url=url, headers=self.headers).text,若果没有对中文进行编转码,就会获取到乱码

,解决方法
response = requests.get(url=url, headers=self.headers).text.encode('iso-8859-1').decode('gbk')4. 二级和三级目录的网址都需要拼接href = 'http://pic.netbian.com' + li.xpath('./a/@href')[0]
img_url = 'http://pic.netbian.com' + tree.xpath('//*[@id="img"]/img/@src')[0]5.爬多了会被反爬,最好把cookie加上
(五)完整代码
# 定义一个爬虫类
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)
2022年07月24日 04点07分
1

(一)分析目标网址1.目标网页每页20张图片,需要获取1000张图片则需要翻页第一页网址:https://pic.netbian.com/index.html
第二页网址:https://pic.netbian.com/index_2.html
第三页网址:https://pic.netbian.com/index_3.html
观测每一页的网址发现除了第一页index后不带数字,其他页面index后面的数字都是对应的页码
2.不能出现相同的图片,这里使用图片名称来判断,如果图片名称一样,则判断图片一样,不重复下载。3.网页中开发目标网址,获取图片名称4.使用python创建一个面向目标网址的类,及写入获取目标图片的方法5.使用os库来创建一个文件夹
(二)获取目标位置1.在网页地址栏输入目标网址,打开网页;2.按下F12打开开发者工具,下图中红色部分;

3.鼠标点击资源定位符
然后点击需要定位的图片,如
定位到目标位置
在这就可以获取到图片网址(src,注意网址不全需要拼接)和名称(<b>标签里),通过xpath就可以提取出来;4.通过下载发现用src下载的图片分辨率比较小

5.点击
进入目标图片的二级目录,并按F12打开开发者工具,资源定位符点击目标图片
,发现二级目录下也有个src,且与一级目录的不一样;6.点击
进入图片的三级目录,发现是我们需要的图片网址。
(三)python代码实现1.定义一个爬虫类,及方法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):
2. init# 当前文件夹如果没有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'
}3.获取所有图片的二级目录网址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)4.获取图片的三级目录网址(及分辨率较高的图片网址)# 对二级网址发起请求
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)5.并发及一级获取图片二进制数据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)6.保存图片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}下载完成')(四)小tips1.第一页的网址并不是https://pic.netbian.com/index_1.html,而是https://pic.netbian.com/index.html,所以第一页要特殊处理,使用if判断,如果是第一页,直接定义url='https://pic.netbian.com/index.html',其他页码就用f格式化;2.获取图片名称时不能再a标签里@title提取
,因为第二页a便签就没有title属性了,会获取不到图片名称而要在a标签的b便签下获取 文本属性
3.获取图片名称时response = requests.get(url=url, headers=self.headers).text,若果没有对中文进行编转码,就会获取到乱码
,解决方法response = requests.get(url=url, headers=self.headers).text.encode('iso-8859-1').decode('gbk')4. 二级和三级目录的网址都需要拼接href = 'http://pic.netbian.com' + li.xpath('./a/@href')[0]
img_url = 'http://pic.netbian.com' + tree.xpath('//*[@id="img"]/img/@src')[0]5.爬多了会被反爬,最好把cookie加上
(五)完整代码
# 定义一个爬虫类
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)