爬取唯美女生网站
前几天刚好看到有人在教学爬取唯美女生网站(https://www.vmgirls.com
)的图片,大致听了一下,只是介绍了一次爬取某一个小姐姐的照片,因此就尝试做一个爬取全站小姐姐照片的爬虫,也算是对最近所学知识的应用和总结。
明确目标和分解任务
明确目标
通过爬虫爬取唯美女生网站上所有小姐姐的照片。
分解任务
1.要保存所有小姐姐的照片就需要依次分别保存每个小姐姐的照片,就需要访问每一篇文章,并获得每一张照片的地址;
2.要保存每位小姐姐的全部照片就需要把文章的每一页进行访问,以获得每一页上的每一张照片;
任务要求
1.获得每篇文章的链接;
2.获得每篇文章每一页的链接;
3.获得每篇文章每一页中的照片链接;
4.保存每张照片;
5.为了方便整理,用以文章名字命名的文件夹保存照片;
所需模块和语句
所需模块
1.requests模块 是python实现的爬取网页最简单易用的HTTP模块,用于访问网页;
2.re模块 正则表达式模块,用于对获得的数据进行清洗,使得规范;
3.os模块 操作系统模块,用于创建文件夹;
4.time模块 时间模块,用于设定延时,避免网站崩溃;
import requests # 导入requests库
import re # 导入正则表达式库
import os # 导入操作系统库
import time # 导入时间库
所需语句和函数
def 语句 定义函数,对于重复的步骤进行调用;
for 语句 循环语句,对于步骤进行循环;
break语句 终止循环语句,对于满足某一条件后的内容进行终止循环
if 语句 条件语句,根据条件确定执行步骤;
else 语句 条件语句 ,根据条件确定执行步骤;
len() 方法返回对象(字符、列表、元组等)长度或项目个数;
具体步骤
分析网站
打开唯美女生网站(https://www.vmgirls.com
),页面分为多个栏目,而在栏目【站点地图】(https://www.vmgirls.com/sitemap.shtml
)中有最新文章内容,基本涵盖整个网站所有的文章,因此将通过访问该网站来获得每个文章的网址。查看源代码发现,所有文章网址均有序排列。
……
<li><a href="https://www.vmgirls.com/13404.html" title="想把夏日的阳光寄给冬日的你" target="_blank">想把夏日的阳光寄给冬日的你</a></li>
<li><a href="https://www.vmgirls.com/13344.html" title="少女情怀总是诗" target="_blank">少女情怀总是诗</a></li>
<li><a href="https://www.vmgirls.com/13333.html" title="谁的青春,被藏在那个夏天" target="_blank">谁的青春,被藏在那个夏天</a></li>
<li><a href="https://www.vmgirls.com/13322.html" title="初恋粉色系" target="_blank">初恋粉色系</a></li>
<li><a href="https://www.vmgirls.com/13299.html" title="世间美好,与你环环相扣" target="_blank">世间美好,与你环环相扣</a></li>
<li><a href="https://www.vmgirls.com/13271.html" title="夏天里藏了一个可爱的你" target="_blank">夏天里藏了一个可爱的你</a></li>
<li><a href="https://www.vmgirls.com/13230.html" title="遇见一个小可爱" target="_blank">遇见一个小可爱</a></li>
……
因此,首先将通过访问该页面获得所有文章链接。
爬取所有文章所在页面
在使用爬虫时要想利用‘user-agent’进行伪装。
user = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
#打开浏览器输入:“about:version”,查看“用户代理”,即本机的user-agent
}
接下来,使用requests模块中的get()函数来模拟访问并将得到的内容保存在变量response中,并将获得的网页内容用文本形式显示出来。
response = requests.get('https://www.vmgirls.com/sitemap.shtml',headers=user) # 用requests库的get函数访问网页,用headers进行伪装,获得所有文章网址
html = response.text # 用文本显示访问网页得到的内容
利用正则表达式获得每篇文章网址
获得网页内容后通过正则表达式来获得所有文章的链接。观察获得的网页内容中的所有文章链接均为`https://www.vmgirls.com/XXXXX.html的形式,因而可以利用正则表达式来获得所有文章网址。
urls_wz = re.findall('https://www.vmgirls.com/\d*.html', html) # 用正则表达式获得文章的所有网址
print(urls_wz) # 打印显示所有网址,查看是否获得正确
依次访问每篇文章来获得图片网址并提取
再次利用requests.get()函数结合for语句来获得每篇文章中的图片网址,并利用正则表达式对获得的网页中的图片网址进行清洗提取。该网站是私人网站,因此在访问网页的过程中加上了延时。
for url_wz in urls_wz:
time.sleep(30) # 设定30秒延时
print('正在爬取:' + str(url_wz) + "的图片") # 查看正在爬取的网址
response = requests.get(url_wz, headers=user) # 用requests库的get函数访问文章网页,用headers进行伪装
html = response.text # 用文本显示访问网页得到的内容
urls_tp = re.findall('<a href="(.*?)" alt=".*?" title=".*?">', html) # 正则表达式获得图片网址
print(urls_tp) # 打印显示文章图片网址,以查看和测试是否正确
爬取文章的每一页中的图片网址并提取
通过查看文章,发现部分文章存在多页的情况,每页上均有图片,因此需要对每一页文章进行爬取来获得图片网址。打开文章第2页,第3页后发现网址的格式为https://www.vmgirls.com/XXXX/page-X.html
,因此可以通过将网址分割为https://www.vmgirls.com/XXXX
后与/page-
利用range()函数来生成数字后和.html
进行拼接。
for i in range(2,6): #利用range(2,6)函数和for语句结合依次生成数字2,3,4,5
url_wz = "".join(url_wz) #将url_wz转换为字符串
url_dfy = re.findall('(.*?).html',url_wz) #利用正则表达式获得https://www.vmgirls.com/XXXX部分
url_dfy = "".join(url_dfy) #将url_dfy转换为字符串
url_fy = url_dfy + '/page-' + str(i) + '.html' #将字符串进行拼接获得完整网址
print(url_fy) #打印拼接后的网址,观察是否正确
time.sleep(30) # 设定30秒延时
response = requests.get(url_fy,headers = user) #访问拼接后的网址
html = response.text #用文本的形式保存返回的数据
urls_fy_pic = re.findall('<a href="(.*?)" alt=".*?" title=".*?">', html) #利用正则表达式获得每个图片的网址
判断文章每页是否有图片
在设定文章翻页时可能设定了相对较多的页码,而文章实际并不存在相应的页码,因此要进行判断,并决定下一步的运行程序,如果在页面中得到图片网址则执行相关的保存,否则直接输出("第%s页面无图片,即将爬取下一篇文章"%str(i))
后使用break语句终止循环。
if len(urls_fy_pic):
for url in urls_fy_pic: # 循环获取每一个图片网址
file_name = url.split('/')[-1] # 取每个url最后的部分
time.sleep(5) # 设定5秒延时
response = requests.get(url, headers=user) # 用requeste库的get函数访问图片网址,用headers进行伪装
print("正在保存第%s页的图片……"%str(i))
print("第%s页保存成功"%str(i))
else:
print("第%s页面无图片,即将爬取下一篇文章"%str(i))
break #终止无图片页面的循环
定义创建目录和保存函数
在爬取整个网站过程中由于页面相对较多,同时为了及时获得每一页的图片,因此在获得相关图片地址后就进行目录创建和保存,因为要多次调用,因而定义一个函数来方便使用。
def dir_save():
dir_name = re.findall('<h1 class="post-title h3">(.*?)</h1>', html)[-1] # 正则表达式创建目录名字
if not os.path.exists(dir_name): # 判断文件夹是否存在,如果不存在:
os.mkdir(dir_name) # 创建一个文件夹
with open(dir_name + '/' + file_name, 'wb') as f: # 用wb模式打开创建文件,w写模式
f.write(response.content) # 写入二进制文件内容
完整代码如下
"""导入模块"""
import requests # 导入requests库
import re # 导入正则表达式库
import os # 导入操作系统库
import time # 导入时间库
print("爬虫程序正在执行中,因设置有延时,故页面显示有些迟缓……")
def dir_save():
dir_name = re.findall('<h1 class="post-title h3">(.*?)</h1>', html)[-1] # 正则表达式创建目录名字
if not os.path.exists(dir_name): # 判断文件夹是否存在,如果不存在:
os.mkdir(dir_name) # 创建一个文件夹
with open(dir_name + '/' + file_name, 'wb') as f: # 用wb模式打开创建文件,w写模式
f.write(response.content) # 写入二进制文件内容
user = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
}
response = requests.get('https://www.vmgirls.com/sitemap.shtml',headers=user) # 用requests库的get函数访问总网页,用headers进行伪装,获得所有文章网址
html = response.text # 用文本显示访问网页得到的内容
urls_wz = re.findall('https://www.vmgirls.com/\d*.html', html) # 用正则表达式获得文章的所有网址
#print(urls_wz) # 打印显示所有网址
for url_wz in urls_wz:
time.sleep(30) # 设定30秒延时
print('正在爬取:' + str(url_wz) + "的图片") # 查看正在执行的网址,以判断是否下载完整
response = requests.get(url_wz, headers=user) # 用requests库的get函数访问网页,用headers进行伪装
#print(response.text) #打印网页
html = response.text # 用文本显示访问网页得到的内容
urls_tp = re.findall('<a href="(.*?)" alt=".*?" title=".*?">', html) # 正则表达式获得图片网址
#print(urls_tp) # 打印显示文章图片网址
if len(urls_tp):
for url_tp in urls_tp: # 循环获取每一个图片网址
# 图片的名字
file_name = url_tp.split('/')[-1] # 取每个url_tp最后的部分
time.sleep(10) # 设定10秒延时
response = requests.get(url_tp, headers=user) # 用requeste库的get函数访问图片网址,用headers进行伪装
print("正在保存图片中……")
dir_save()
print("保存第一页图片完毕!!!")
for i in range(2,100): #用range()函数分别输出2-99
url_wz = "".join(url_wz)
url_dfy = re.findall('(.*?).html',url_wz)
url_dfy = "".join(url_dfy)
url_fy = url_dfy + '/page-' + str(i) + '.html'
#print(url_fy)
time.sleep(30) # 设定30秒延时
response = requests.get(url_fy,headers = user)
html = response.text
urls_fy_pic = re.findall('<a href="(.*?)" alt=".*?" title=".*?">', html)
#print(urls_fy_pic) #查看图片网址
if len(urls_fy_pic):
for url in urls_fy_pic: # 循环获取每一个图片网址
file_name = url.split('/')[-1] # 取每个url最后的部分
time.sleep(5) # 设定5秒延时
response = requests.get(url, headers=user) # 用requeste库的get函数访问图片网址,用headers进行伪装
print("正在保存第%s页的图片……"%str(i))
dir_save()
print("第%s页保存成功"%str(i))
else:
print("第%s页面无图片,即将爬取下一篇文章"%str(i))
break
else:
print("原有正则表达式保存不成功的网址是:" + str(url))
仅供参考,欢迎多多指教!