无需密码自动登录,系统用户名shiyanlou
本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到桌面上的程序:
使用GVim编辑器输入实验所需的代码及文件,使用Xfce终端运行所需命令进行操作。
实验报告可以在个人主页中查看,其中含有每次实验的截图及笔记,以及每次实验的有效学习时间(指的是在实验桌面内操作的时间,如果没有操作,系统会记录为发呆时间)。这些都是您学习的真实性证明。
实验楼虚拟机,自带了python2.X和python3.X版本,无需安装,本实验基于 python2。
这一节呢,利用上一节提到的知识点,进行单网页的图片爬取和下载至本地
body标签 -> wrapper -> container -> pagecontent -> maincontent -> postContent -> picture -> p (查阅HTML源码,我只用了后面三个)
匹配用到的正则表达式(我用id和class匹配):
'<div.*?class="postContent.*?>.*?<p>(.*?)</p>' 获取图片链接那段html代码
'<div.*?id="picture.*?>.*?<p>(.*?)</p>' 查阅上级获得的html中,picture那块代码
'<img.*?src="(.*?)".*?>' 从上一个表达式中,获取图片链接
'.*/(.*?.jpg)' 从图片链接中,提取图片名,这个是最简单的
判断文件时候存在,如果存在,不下载,节约时间
如果文件不存在,下一步创建新文件,读写模式打开
打开图片链接,将缓存写入到文件中
关闭图片文件,完成
以上呢就是本节内容要实现的全部功能,接下来贴上代码
这里呢,按功能的先后顺序,逆序贴代码,不过代码有点长,我会在'def'后面附上注释
#文件名:meizi_page_download
import urllib2
import os
import re
#loadurl()这个函数呢,是防打开链接超时,如果超时返回空字符,则主调函数会再次调用(while语句就可以实现),正常的话返回html代码,一个网页不算大,如果你的网络超级好,timeout可以缩短
def loadurl(url):
try:
conn = urllib2.urlopen(url,timeout=5)
html = conn.read()
return html
except urllib2.URLError:
return ''
except Exception:
print("unkown exception in conn.read()")
return ''
#这里是图片保存的代码被调函数,timeout=5设置超时时间,一个500k不到的图片,5秒时间算长的了,超时的话,返回失败
def download(url,filename):
try:
conn = urllib2.urlopen(url,timeout=5)
f = open(filename,'wb')
f.write(conn.read())
f.close()
return True
except urllib2.URLError:
print 'load',url,'error'
return False
except Exception:
print("unkown exception in conn.read()")
return ''
#保存图片的逻辑代码块
def save_pic(url,path):
searchname = '.*/(.*?.jpg)'
name = re.findall(searchname,url)
filename = path +'/'+ name[0]
print filename + ':start' #控制台显示信息
#下面的代码,当下载成功,break跳出就好了,如果存在,直接结束这个函数
#定义了在下载图片时遇到错误的重试次数
tryTimes = 3
#当重试次数没有用完时,则尝试下载
while tryTimes != 0:
tryTimes -= 1
if os.path.exists(filename):
print filename,' exists, skip'
return True
elif os.path.exists(filename):
os.mknod(filename)
if download(url,filename):
break
if tryTimes != 0:
print(filename + ": over")
else:
print(url + " :Failed to download")
#控制台显示信息
#这个函数,相当于一个中介,我只是把for循环代码提出就得到了这个函数
def pic_list(picList,path):
picurl = ''
for picurl in picList:
save_pic(picurl,path)
#图片下载的主逻辑函数,获取图片链接,然后传给pic_list(),等结果(其实也没结果,就是等退出)
def picurl(url,path):
if os.path.exists(path):
print path, 'exist'
else:
os.makedirs(path)
html = ''
while True:#这里和下载图片是一个道理,细看即可
html = loadurl(url)
if html == '':
print 'load', url,'error'
continue
else:
break
#其实这里呢,也是后期发现的一个小bug,这个网站的前后代码有不同(目前而言发现的一处),在rePicContent1运行到后面,是匹配不到的,导致rePicList返回的结果也是空,也就造成了这个符号[0]报错,因为没有任何值,越界错误,单线程会在这里报错并停止运行。rePicContent2其实是我解决bug的另一个匹配正则式,被我发现的页面是这个--http://www.meizitu.com/a/454.html,有兴趣的去对比看看
rePicContent1 = '<div.*?id="picture.*?>.*?<p>(.*?)</p>'
rePicContent2 = '<div.*?class="postContent.*?>.*?<p>(.*?)</p>'
rePicList = '<img.*?src="(.*?)".*?>'
#这里对re.S做个介绍,re.S是可以不添加的,加上之后,它的作用就是能忽略换行符,将两条作为一条来匹配。html代码碰上换行的概率是很高的,所以我一致采用re.S(下文有配图)
picContent = re.findall(rePicContent1, html,re.S)
if len(picContent) <=0:
picContent = re.findall(rePicContent2, html,re.S)
if len(picContent) <=0:
print 'load false, over download this page and return'
return False
else:
picList = re.findall(rePicList,picContent[0],re.S)
pic_list(picList,path)
#url = 'http://www.meizitu.com/a/454.html'这两行是我函数测试所用
#picurl(url,'/home/shiyanlou/Desktop/demo454')
声明,在运行代码的时候,保险起见别插入中文,特别是linux环境,容易报错,另外在这里附上re.S的截图(没有3吧) 代码到这里就结束了,底层的图片获取链接并保存,完成,附上实验楼的截图一张(一开始报错,第二次就好了,运行之前,请确保你有外网权限,用下Firefox看下网站就行,如果没用,请本机测试)
请继续下一个实验