前言:
其实我之前写过一篇爬取MM图片的文章,但是碍于尺度的问题,文章改了又改才过审,但是作为一个爬虫,怎么能没有爬取图片的案例呢,所以我又发现了一个不错的网站,里面的MM也不错,而且尺度也正常,话不多说,开爬!!
本案例网址:http://tuchong.com/tags/%E7%BE%8E%E5%A5%B3
一、分析网页
从图可以看出每一张图片对应一个链接,每一个链接里面就是该图片这个模特的所有图片,打开开发者工具来具体分析一下,可以分析出这个网页的图片加载都是动态加载的,你滚轮滑动向下,图片一直会加载,但是网址没有改变,如图:
既然知道了是动态加载的网页,那我们就直接定位到XHR选项,定位到包含有图片数据的网页:
可以看出,定位的数据里面是属于json的数据,数据里面包含了该模特的一些信息,有标题信息,有一些摄影信息,本案例是爬取图片,所以我们只需要找到每一个模特所在的网址链接,就可以。下面我们来打开一个美女图片的链接继续分析,我们找到了包含图片的网址,如图:
可以看出,这个包含图片的网址就是json数据里面的对应的url选项里面的网址。每一个模特的系列图片就包含在这个网址里面,我们只需要请求这个网址,得到请求数据后,就可以提取出图片的真实链接地址了。
现在说一下,大概的思路,我们通过发送请求,获取响应数据,获取到每个模特所在的图片地址,然后请求这个地址,提取出这个网址里面的模特图片真实链接,最后保存图片。
本案例所用到的模块:
import requests
import os
import wget
import parsel
二、发送请求,获取响应数据
def parse_url(self, url):
"""发送请求,获取响应数据的方法
Args:
url ([type]): [description]
Returns:
[type]: [description]
"""
response = requests.get(url, headers=self.HEADERS)
if response.status_code == 200:
return response.json()
三、获取每个模块所在的网页网址
def get_picUrl(self, json_str):
"""获取每个图片的链接地址的方法
Args:
json_str ([type]): [description]
Yields:
[type]: [description]
"""
for data in json_str.get('postList'):
# 提取图片总链接地址
yield {'pic_index_url': data.get('url')}
四、对提取到的网址进行请求,获取响应
def parse_pic_url(self, url):
"""发送请求,获取响应数据的方法
Args:
url ([type]): [description]
Returns:
[type]: [description]
"""
response = requests.get(url, headers=self.HEADERS)
if response.status_code == 200:
return response.text
五、提取图片的真实地址和构建出图片名字
def get_pic_url(self, html_str):
"""提取图片的真实地址和图片名字的方法
Args:
html_str ([type]): [description]
Returns:
[type]: [description]
"""
html = parsel.Selector(html_str)
pic_urls = html.css('.post-content>img::attr(src)').extract()
pic_names = [i.split("/")[-1] for i in pic_urls]
return pic_urls, pic_names
六、保存图片
def down_pic(self, pic_url, pic_id):
"""下载图片的方法
Args:
pic_url ([type]): [description]
pic_id ([type]): [description]
"""
path = os.path.join("爬取图虫网MM", "MM", f"{pic_id}")
file_name = wget.download(pic_url, out=path)
print(f"{file_name}---下载完成")
完成效果展示:
完整代码:
# 导入需要的模块
import requests
import os
import wget
import parsel
class MMSpider:
"""爬取图虫网图片数据"""
def __init__(self, page):
self.API_URL = f'http://tuchong.com/rest/tags/%E7%BE%8E%E5%A5%B3/posts?page={str(page)}&count=20&order=weekly'
self.HEADERS = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
def parse_url(self, url):
"""发送请求,获取响应数据的方法
Args:
url ([type]): [description]
Returns:
[type]: [description]
"""
response = requests.get(url, headers=self.HEADERS)
if response.status_code == 200:
return response.json()
def get_picUrl(self, json_str):
"""获取每个图片的链接地址的方法
Args:
json_str ([type]): [description]
Yields:
[type]: [description]
"""
for data in json_str.get('postList'):
# 提取图片总链接地址
yield {'pic_index_url': data.get('url')}
def parse_pic_url(self, url):
"""发送请求,获取响应数据的方法
Args:
url ([type]): [description]
Returns:
[type]: [description]
"""
response = requests.get(url, headers=self.HEADERS)
if response.status_code == 200:
return response.text
def get_pic_url(self, html_str):
"""提取图片的真实地址和图片名字的方法
Args:
html_str ([type]): [description]
Returns:
[type]: [description]
"""
html = parsel.Selector(html_str)
pic_urls = html.css('.post-content>img::attr(src)').extract()
pic_names = [i.split("/")[-1] for i in pic_urls]
return pic_urls, pic_names
def down_pic(self, pic_url, pic_id):
"""下载图片的方法
Args:
pic_url ([type]): [description]
pic_id ([type]): [description]
"""
path = os.path.join("爬取图虫网MM", "MM", f"{pic_id}")
file_name = wget.download(pic_url, out=path)
print(f"{file_name}---下载完成")
def run(self):
"""
实现主要逻辑思路
"""
# 1.发送请求,获取响应数据
json_str = self.parse_url(self.API_URL)
# 2.提取图片总链接地址
data_url = self.get_picUrl(json_str)
for data in data_url:
pic_index_url = data.get('pic_index_url')
# 3.对图片总链接地址发送请求,获取响应数据
html_str = self.parse_pic_url(pic_index_url)
# 4.提取图片真实地址和图片名字
pic_urls, pic_names = self.get_pic_url(html_str)
for pic_url, pic_name in zip(pic_urls, pic_names):
# 5.下载图片地址
self.down_pic(pic_url, pic_name)
if __name__ == "__main__":
for page in range(1, 3):
mm_spider = MMSpider(page)
mm_spider.run()