前言:
好久没有更新博文了,因为工作的关系,一直没有更新博文,今天有空,就给大家带来一个爬图片的小案例。今天的目标网站就是堆糖网,关于爬取这个网站图片的案例,肯定大家都看到很多,基本都是通过搜索图片的关键字,然后找到ajax网页,然后请求这个网页,获取到他的json数据,最后提取出图片。我们今天就用另一种思路来给大家爬取这个网站的图片。
本案例网站:https://www.duitang.com/blog/?id=1345325138
一、分析网页
既然说了,是用另一种思路来爬取图片,那我们就需要具体分析一下,这个网站。打开网页,我们看到该网页就只有一张图片,如图:
肯定有小伙伴要问了,就一张图片,你不会就是说只爬着一张图片吧,这就是你说的另一种爬取吗,有点坑人啊。
不要着急嘛,肯定不能这样了,我们的需求肯定是要不断爬取该网站的图片的,那就这一张图片要怎么实现爬取网站的大部分图片呢,现在我们就要进一步分析一下这个网页,我们看到当我们鼠标移动到该图片的右半部分的时候,网页会有一个箭头的显示,会有下一页的提示,然后我们在这个部分点击图片,然后网页就会跳转到另一张图片了,如图:
然后我们在点击这张图片,一样网页就会跳转到下下一张图片,我们这个案例爬取的思路就是利用网站点击下一张图片,然后跳转到下一张图片的特性,来循环爬取网站上的图片。
既然知道了每一张图片可以跳转到下一张图片,那网页HTML里面肯定就会有包含下一张图片的链接地址,我们只需要找到图片的真实地址和包含下一张图片的链接地址,不断的执行上面的操作,这样就可以把图片爬取下来了。
通过分析网页的HTML源代码,可以知道图片的真实地址是这个:
包含下一页的地址链接是:
本案例所用到的模块:
import requests
import parsel
import re
import os
import wget
二、对目标网站发送请求,获取响应数据
def parse_url(self, url):
"""
发送请求,获取响应数据的方法
:param url:
:return:
"""
response = requests.get(url, headers=self.HEADERS)
if response.status_code == 200:
return response.text
三、获取图片的真实地址和图片ID的方法
def get_pic_data(self, html_str):
"""
获取图片地址和图片ID的方法
:param html_str:
:return:
"""
html = parsel.Selector(html_str)
# 提取图片真实地址
pic_url = html.css('.js-favorite-blogimg::attr(src)').extract_first()
pattern = re.compile('href="/blog/\?id=(\d+)"', re.S)
# 提取图片ID
pic_ids = pattern.findall(html_str)
return pic_url, pic_ids
四、对跳转的下一页进行发送请求,获取相应数据
def get_params(self, id):
"""
构建params参数的方法
:param id:
:return:
"""
return {
"id": id
}
def parse_url2(self, pic_id, params):
"""
再次发送请求,获取响应数据的方法
:param pic_id:
:param params:
:return:
"""
url = self.INDEX_URL.split("?")[0] + f"?id={pic_id}"
response = requests.get(url, headers=self.HEADERS, params=params)
if response.status_code == 200:
return response.text
五、保存图片
def save_pic(self, pic_url):
"""
保存图片的方法
:param pic_url:
:return:
"""
pic_name = pic_url.split("/")[-1]
path = os.path.join("MM", pic_name)
path_name = wget.download(pic_url, out=path)
print(path_name)
完成效果展示:
完整代码:
# 导入需要的模块
import requests
import parsel
import re
import os
import wget
class TuiTangSpider:
"""爬取推糖网图片"""
def __init__(self):
self.INDEX_URL = 'https://www.duitang.com/blog/?id=1345325138'
self.HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36"
}
def parse_url(self, url):
"""
发送请求,获取响应数据的方法
:param url:
:return:
"""
response = requests.get(url, headers=self.HEADERS)
if response.status_code == 200:
return response.text
def get_pic_data(self, html_str):
"""
获取图片地址和图片ID的方法
:param html_str:
:return:
"""
html = parsel.Selector(html_str)
# 提取图片真实地址
pic_url = html.css('.js-favorite-blogimg::attr(src)').extract_first()
pattern = re.compile('href="/blog/\?id=(\d+)"', re.S)
# 提取图片ID
pic_ids = pattern.findall(html_str)
return pic_url, pic_ids
def get_params(self, id):
"""
构建params参数的方法
:param id:
:return:
"""
return {
"id": id
}
def parse_url2(self, pic_id, params):
"""
再次发送请求,获取响应数据的方法
:param pic_id:
:param params:
:return:
"""
url = self.INDEX_URL.split("?")[0] + f"?id={pic_id}"
response = requests.get(url, headers=self.HEADERS, params=params)
if response.status_code == 200:
return response.text
def save_pic(self, pic_url):
"""
保存图片的方法
:param pic_url:
:return:
"""
pic_name = pic_url.split("/")[-1]
path = os.path.join("MM", pic_name)
path_name = wget.download(pic_url, out=path)
print(path_name)
def run(self):
"""
实现主要逻辑思路
:return:
"""
# 1.发送请求,获取响应数据
html_str = self.parse_url(self.INDEX_URL)
# 2.提取图片的地址和图片id
pic_url, pic_ids = self.get_pic_data(html_str)
# 3.保存图片
self.save_pic(pic_url)
# 4.循环以上的步骤
while True:
params = self.get_params(pic_ids[1])
html_str = self.parse_url2(pic_ids[1], params)
pic_url, pic_ids = self.get_pic_data(html_str)
self.save_pic(pic_url)
if __name__ == '__main__':
tuitang_spider = TuiTangSpider()
tuitang_spider.run()
结语:
该案例就是通过另一种思路来爬取网页的图片的,但是这个案例也又一个弊端,我设置了一个死循环,只要执行该程序就会不断的执行下去,但是我们可以通过一些条件来限制它,这里我就没有设置了,感兴趣的小伙伴可以自己设置一下。