学习爬虫技术近一个月,参考一位大牛的博客,钻研近两个星期,终于完成该程序,虽然写法还不够简洁,也不够规范,但对于我这个小白来说,这段学习经历是弥足珍贵的
以下是博客地址:https://cuiqingcai.com/3179.html
感谢崔庆才大牛
该代码难点如下
1.多层页面,进入首页网址后先要获取当前页面所有套图的地址,再根据获取的地址逐一访问,进入套图页面后再要获取所有图片的地址,最后才是保存图片,在代码中需要使用两个循环嵌套来进行地址获取
2.页面获取到的数据略杂乱,有大量用不到的数据,例如在获取所有套图地址时,会出现如下情况
可以看到打印出来每个套图的地址都有两个,为了解决该问题,代码中获取套图网址之前加上一个if判断去除重复网址
3.网站有反盗链机制,导致通常方法获取到的图片都是这样的
所以需要在请求头中加上Referer来模拟成真实浏览器对服务器进行访问,添加Referer也非常简单,只需要复制当前页面的网址加到请求头中即可,注意在首页的请求头和套图页面的请求头中都需要加上Referer
from bs4 import BeautifulSoup
import requests
import urllib
import os
import time
time_start=time.time()
url = 'https://www.mzitu.com'
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/72.0.3626.121 Safari/537.36', 'Referer': 'http://www.mzitu.com/', }
page = urllib.request.Request(url, headers = headers) # 模拟浏览器对服务器发送请求
html = urllib.request.urlopen(page).read() # 获取页面信息
soup = BeautifulSoup(html, 'html.parser') # 使用BeautifulSoup库提取html中的数据
div1 = soup.find('div', class_='postlist').find_all('a') # 获取页面中所有div标签中class为postlist的,再获取该div标签下所有a标签到变量div1中
flag = 1 #判断a标签的变量
t_num = 1 #计算当前套图数量的变量
t_img = 0
div1.pop() #获取到的div标签后4条是没用的,使用4次.pop删除(括号内容为空默认删除最后一条)
div1.pop()
div1.pop()
div1.pop()
path1 = 'D:\壁纸\python2\\' # 定义存储路径
for a in div1: # 因为div1中有多个a标签,所以使用循环依次处理每一个a标签(外层循环,获取页面中每个套图url)
title = a.get_text() # 获取a标签中文本(套图名称)
if flag %2 == 0 : # div1中每个a标签都有两条,使用一个自增变量进行判断,当a是第偶数条时才执行
link = a.get('href') # 获取a标签中链接(每个套图url)
html1 = requests.get(link,headers=headers) #使用requests.get直接获取链接link中的页面内容
soup1 = BeautifulSoup(html1.text,'lxml') #使用BeautifulSoup库提取中html1中的数据
span1 = soup1.find('div',class_ = 'pagenavi').find_all('span')[-2].get_text() #提取页面中所有div标签中class为pagenavi的,再获取最后一个span标签下的文本内容
os.makedirs(os.path.join(path1, title)) #创建套图目录
os.chdir(os.path.join(path1+title)) #切换上一行创建的目录
i = 1 #计算套图中当前图片的变量
print('套图<<<%s>>>开始下载...' % (title))
for b in range(1,int(span1)+1): #b的循环范围在1到最大页数之间(内层循环,获取每个套图中每一页的链接和链接中的图片地址,并下载到本地)
page_url = link+'/'+str(b)
#套图中每一页的地址是有规律的,如www.mzitu.com/12345/1,xxx/12345/2,xxx/12345/3等,所以使用套图地址拼接上斜杠和一个自增变量即可得到每一页的地址
headers2 = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/72.0.3626.121 Safari/537.36', 'Referer': link, }
#网站有防盗链机制,获取套图页面时要加上该页面的Referer(即当前页面url),link存储的是当前套图页面url,可以直接使用
html2 = requests.get(page_url, headers=headers2) #使用requests.get直接获取链接page_url中的页面内容
soup2 = BeautifulSoup(html2.text, 'lxml') #使用BeautifulSoup库提取中html2中的数据
final_link = soup2.find('div',class_ = 'main-image').find('img')['src'] #提取页面div标签中class为main-image的,再获取该div标签中img标签中的src属性内容
final_link_img = requests.get(final_link, headers=headers) #使用requests.get直接获取final_url(图片链接)中的页面内容
f = open(str(i) + '.jpg', 'ab') #定义文件名与文件格式
f.write(final_link_img.content) #使用conctent把每个图片的url写入文件
f.close() #关闭文件
print('(套图%d)第%d张图片下载成功' % (t_num,i))
i += 1
t_img += 1
t_num += 1
flag += 1
time_end=time.time()
print('爬虫统计:共下载%d套图,总计%d张图片,平均每套%d张图片,共耗时%d秒' % ((t_num-1),t_img,(t_img/t_num),(time_end-time_start)))
代码还会继续改进,有不足的地方希望大家多多指教,谢谢