首先声明,本博文为我原创,但是我在看了 崔庆才 博主的文章之后加以自己的实际处理的所得,感谢 崔庆才 博主,写的爬虫文章都好,博主文章地址:http://cuiqingcai.com/3179.html
环境:python 3.6
注:单线程版以在安卓的Qpython(py2.7)上运行成功
第三方库
requests:解析url
beautifulsoup4:不会正则表达式童鞋的福音,可以容易的提取到html文件中各种标签及其属性
安装方法:
pip install requests
pip install beautifulsoup4
如果有错误请自行解决
目标
话说回来,我半年前就开始学习py爬虫,但当时应该是兴趣不足,导致半途而废,所以说兴趣非常重要,我们的目标应该可以使大家有很大的兴趣,激励自己学习爬虫。
原理
学习爬虫,首先是要学习它的原理。打开网址(为了防止和谐我就不上图了 ),大家可以发现,一共有141页,每页都有很多套图,如果要你手动去保存,怎么操作?我想应该是这样,从第一页开始,点进第一个套图,然后保存每张图片,然后进行第二个套图……第一页完了之后第二页,从第一个套图开始,保存保存……这就是原理,当然,虽然这样能达到这个目的,但大家应该没有那么多的时间,那么我们就来学习爬虫,来替我们保存图片。
步骤
1.获取网页源码
用浏览器的F12可以看到网页的源码,但我们现在要用python这样做。
#coding=utf-8
import requests
url = ‘http://www.mzitu.com‘
#设置headers,网站会根据这个判断你的浏览器及操作系统,很多网站没有此信息将拒绝你访问
header = {
‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.204 Safari/537.36‘}
#用get方法打开url并发送headers
html = requests.get(url,headers = header)
#打印结果 .text是打印出文本信息即源码
print(html.text)
如果没问题的话结果会是这样类似
......
$("#index_banner_load").find("div").appendTo("#index_banner");
$("#index_banner").css("height", 90);
$("#index_banner_load").remove();
});
</script>
</body>
</html>
这些就是网页的源码了。
2.寻找所需信息
切换浏览器,右键‘查看网页源代码’,可以发现有很多这样的信息
<li><a href="http://www.mzitu.com/89334" target="_blank"><img width=‘236‘ height=‘354‘ class=‘lazy‘ alt=‘我是标题我是标题我是标题我是标题我是标题我是标题‘ src=‘http://i.meizitu.net/pfiles/img/lazy.png‘ data-original=‘http://i.meizitu.net/thumbs/2017/04/89334_02b06_236.jpg‘ /></a><span><a href="http://www.mzitu.com/89334" target="_blank">我是标题我是标题我是标题我是标题我是标题我是标题我是标题我是标题我是标题我是标题</a></span><span class="time">2017-04-02</span><span class="view">6,788次</span></li>
那么我们只需要提取这些东西就可以了…but:我写不出这么复杂的正则!!!没关系,我们的神器BeautifulSoup要上场了!
我们的步骤是:①将获取的源码转换为BeautifulSoup对象②搜索需要的数据
#coding=utf-8
import requests
from bs4 import BeautifulSoup
url = ‘http://www.mzitu.com‘
header = {
‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.204 Safari/537.36‘}
html = requests.get(url,headers = header)
#使用自带的html.parser解析,速度慢但通用
soup = BeautifulSoup(html.text,‘html.parser‘)
#实际上是第一个class = ‘postlist‘的div里的所有a 标签是我们要找的信息
all_a = soup.find(‘div‘,class_=‘postlist‘).find_all(‘a‘,target=‘_blank‘)
for a in all_a:
title = a.get_text() #提取文本
print(title)
这样就找到了当页所有套图的标题
注意:BeautifulSoup()返回的类型是<class ‘bs4.BeautifulSoup‘>
find()返回的类型是<class ‘bs4.element.Tag‘>
find_all()返回的类型是<class ‘bs4.element.ResultSet‘>
<class ‘bs4.element.ResultSet‘>不能再进项find/find_all操作
3.进入下载
点进一个套图之后,发现他是每个页面显示一个图片。
比如http://www.mzitu.com/26685是某个套图的第一页,后面的页数都是再后面跟/和数字http://www.mzitu.com/26685/2 (第二页),那么很简单了,我们只需要找到他一共多少页,然后用循环组成页数就OK了。
#coding=utf-8
import requests
from bs4 import BeautifulSoup
url = ‘http://www.mzitu.com/26685‘
header = {
‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.204 Safari/537.36‘}
html = requests.get(url,headers = header)
soup = BeautifulSoup(html.text,‘html.parser‘)
#最大页数在span标签中的第10个
pic_max = soup.find_all(‘span‘)[10].text
print(pic_max)
#输出每个图片页面的地址
for i in range(1,int(pic_max) + 1):
href = url+‘/‘+str(i)
print(href)
好了,那么我们接下来就是进行寻找图片地址并且保存了,右键妹纸图片,“检查”可以发现
<img src="http://i.meizitu.net/2014/07/20140711w11.jpg" alt="Beautyleg 美腿写真 No.997 Dora">
那么这就是图片的具体地址了
那么我们的目的就要达成,保存它。
#coding=utf-8
import requests
from bs4 import BeautifulSoup
url = ‘http://www.mzitu.com/26685‘
header = {
‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.204 Safari/537.36‘}
html = requests.get(url,headers = header)
soup = BeautifulSoup(html.text,‘html.parser‘)
#最大页数在span标签中的第10个
pic_max = soup.find_all(‘span‘)[10].text
#找标题
title = soup.find(‘h2‘,class_=‘main-title‘).text
#输出每个图片页面的地址
for i in range(1,int(pic_max) + 1):
href = url+‘/‘+str(i)
html = requests.get(href,headers = header)
mess = BeautifulSoup(html.text,"html.parser")
#图片地址在img标签alt属性和标题一样的地方
pic_url = mess.find(‘img‘,alt = title)
html = requests.get(pic_url[‘src‘],headers = header)
#获取图片的名字方便命名
file_name = pic_url[‘src‘].split(r‘/‘)[-1]
#图片不是文本文件,以二进制格式写入,所以是html.content
f = open(file_name,‘wb‘)
f.write(html.content)
f.close()
不出意外你脚本所在的地方会有12张图片
4.批量下载
上面讲了如何下载一个套图,其实所有的套图下载只是加上两重循环。成品如下:
#coding=utf-8
import requests
from bs4 import BeautifulSoup
import os
import sys
‘‘‘
#安卓端需要此语句
reload(sys)
sys.setdefaultencoding(‘utf-8‘)
‘‘‘
if(os.name == ‘nt‘):
print(u‘你正在使用win平台‘)
else:
print(u‘你正在使用linux平台‘)
header = {‘User-Agent‘:‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.204 Safari/537.36‘}
#http请求头
all_url = ‘http://www.mzitu.com‘
start_html = requests.get(all_url,headers = header)
#保存地址
path = ‘D:/mzitu/‘
#找寻最大页数
soup = BeautifulSoup(start_html.text,"html.parser")
page = soup.find_all(‘a‘,class_=‘page-numbers‘)
max_page = page[-2].text
same_url = ‘http://www.mzitu.com/page/‘
for n in range(1,int(max_page)+1):
ul = same_url+str(n)
start_html = requests.get(ul, headers=header)
soup = BeautifulSoup(start_html.text,"html.parser")
all_a = soup.find(‘div‘,class_=‘postlist‘).find_all(‘a‘,target=‘_blank‘)
for a in all_a:
title = a.get_text() #提取文本
if(title != ‘‘):
print("准备扒取:"+title)
#win不能创建带?的目录
if(os.path.exists(path+title.strip().replace(‘?‘,‘‘))):
#print(‘目录已存在‘)
flag=1
else:
os.makedirs(path+title.strip().replace(‘?‘,‘‘))
flag=0
os.chdir(path + title.strip().replace(‘?‘,‘‘))
href = a[‘href‘]
html = requests.get(href,headers = header)
mess = BeautifulSoup(html.text,"html.parser")
pic_max = mess.find_all(‘span‘)
pic_max = pic_max[10].text #最大页数
if(flag == 1 and len(os.listdir(path+title.strip().replace(‘?‘,‘‘))) >= int(pic_max)):
print(‘已经保存完毕,跳过‘)
continue
for num in range(1,int(pic_max)+1):
pic = href+‘/‘+str(num)
html = requests.get(pic,headers = header)
mess = BeautifulSoup(html.text,"html.parser")
pic_url = mess.find(‘img‘,alt = title)
html = requests.get(pic_url[‘src‘],headers = header)
file_name = pic_url[‘src‘].split(r‘/‘)[-1]
f = open(file_name,‘wb‘)
f.write(html.content)
f.close()
print(‘完成‘)
print(‘第‘,n,‘页完成‘)
5.升级多线程版
#coding=utf-8
import requests
from bs4 import BeautifulSoup
import os
from multiprocessing import Pool
import sys
def find_MaxPage():
all_url = ‘http://www.mzitu.com‘
start_html = requests.get(all_url,headers = header)
#找寻最大页数
soup = BeautifulSoup(start_html.text,"html.parser")
page = soup.find_all(‘a‘,class_=‘page-numbers‘)
max_page = page[-2].text
return max_page
def Download(href,header,title,path):
html = requests.get(href,headers = header)
soup = BeautifulSoup(html.text,‘html.parser‘)
pic_max = soup.find_all(‘span‘)
pic_max = pic_max[10].text # 最大页数
if(os.path.exists(path+title.strip().replace(‘?‘,‘‘)) and len(os.listdir(path+title.strip().replace(‘?‘,‘‘))) >= int(pic_max)):
print(‘已完毕,跳过‘+title)
return 1
print("开始扒取:" + title)
os.makedirs(path+title.strip().replace(‘?‘,‘‘))
os.chdir(path + title.strip().replace(‘?‘,‘‘))
for num in range(1,int(pic_max)+1):
pic = href+‘/‘+str(num)
#print(pic)
html = requests.get(pic,headers = header)
mess = BeautifulSoup(html.text,"html.parser")
pic_url = mess.find(‘img‘,alt = title)
html = requests.get(pic_url[‘src‘],headers = header)
file_name = pic_url[‘src‘].split(r‘/‘)[-1]
f = open(file_name,‘wb‘)
f.write(html.content)
f.close()
print(‘完成‘+title)
def download(href,header,title):
html = requests.get(href,headers = header)
soup = BeautifulSoup(html.text,‘html.parser‘)
pic_max = soup.find_all(‘span‘)
#for j in pic_max:
#print(j.text)
#print(len(pic_max))
pic_max = pic_max[10].text # 最大页数
print(pic_max)
‘‘‘
#安卓端需要此语句
reload(sys)
sys.setdefaultencoding(‘utf-8‘)
‘‘‘
if __name__==‘__main__‘:
if (os.name == ‘nt‘):
print(u‘你正在使用win平台‘)
else:
print(u‘你正在使用linux平台‘)
header = {
‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.204 Safari/537.36‘}
# http请求头
path = ‘D:/mzitu/‘
max_page = find_MaxPage()
same_url = ‘http://www.mzitu.com/page/‘
#线程池中线程数
pool = Pool(5)
for n in range(1,int(max_page)+1):
each_url = same_url+str(n)
start_html = requests.get(each_url, headers=header)
soup = BeautifulSoup(start_html.text, "html.parser")
all_a = soup.find(‘div‘, class_=‘postlist‘).find_all(‘a‘, target=‘_blank‘)
for a in all_a:
title = a.get_text() # 提取文本
if (title != ‘‘):
href = a[‘href‘]
pool.apply_async(Download,args=(href,header,title,path))
pool.close()
pool.join()
print(‘所有图片已下完‘)
最后结果在这:
完结撒花~~~