底层:单网页多图下载,难度中等--wh02

底层:单网页多图下载

一、实验说明

1.1. 环境登录

无需密码自动登录,系统用户名shiyanlou

1.2. 环境介绍

本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到桌面上的程序:

  1. Xfce终端: Linux命令行终端,打开后会进入shell环境,可以使用Linux命令
  2. Firefox:浏览器,可以用在需要前端界面的课程里,只需要打开环境里写的HTML/JS页面即可
  3. GVim:非常好用的编辑器,最简单的用法可以参考课程Vim编辑器

1.3. 环境使用

使用GVim编辑器输入实验所需的代码及文件,使用Xfce终端运行所需命令进行操作。

实验报告可以在个人主页中查看,其中含有每次实验的截图及笔记,以及每次实验的有效学习时间(指的是在实验桌面内操作的时间,如果没有操作,系统会记录为发呆时间)。这些都是您学习的真实性证明。

实验楼虚拟机,自带了python2.X和python3.X版本,无需安装,本实验基于 python2。

二、课程介绍

这一节呢,利用上一节提到的知识点,进行单网页的图片爬取和下载至本地

三、功能详解

  • 从网页的html中,获取我们需要的图片链接,打开网页,这个页面下,一共有10张图片是我们需要爬取的,查看网页源码,找到这十张图片的代码,都是
    的格式,但是除了这几张,该网页里面其他的图片也是用img标签,所有只用img匹配,是不太好控制正确率的,另外我在ubuntu下用spy
  • der查阅这个链接html时中文全为乱码,我也就放弃了中文匹配,我用的笨方法就是先找父标签,依次往里直至寻找到img标签,具体路径如下

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吧)
res
res

代码到这里就结束了,底层的图片获取链接并保存,完成,附上实验楼的截图一张(一开始报错,第二次就好了,运行之前,请确保你有外网权限,用下Firefox看下网站就行,如果没用,请本机测试)
shiyanlou
shiyanlou

请继续下一个实验

Python3教程、项目网站--传送门

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容