zoukankan      html  css  js  c++  java
  • Python爬虫简单实现之Q乐园图片下载

    根据需求写代码实现。然而跟我并没有什么关系,我只是打开电脑望着屏幕想着去干点什么,于是有了这个所谓的“需求”。

    终于,我发现了Q乐园——到底是我老了还是我小了,这是什么神奇的网站,没听过啊,就是下面酱紫儿——

    (虽然小广告有点多,一度以为这并不是什么“正经”的网站...)

    我并不是二次元,只是觉得动漫图片还算是“老少皆宜”(“少儿不宜”多尴尬),就决定爬一下动漫图片好了。就是下面那个样子:

    鼠标右键——查看源代码,别问我用得什么浏览器。网页大概就是下面这个样:

    我好像看到了图集名称,“窗外繁华盛开”(窗内我一口老血),“你已经有别的小朋友了 我自己回家就好啦”(说好的老少皆宜,已经隐隐感受了到了早*的味道)

    点开一个图集,看下“窗外繁华盛开”吧,还算美~

    然后我们还是右键查看源代码(说了不告诉你我用的什么浏览器)——

    里面的“http://略略略略略略.jpg”就是图集中图片对应的地址了,比如http://v1.qzone.cc/pic/201709/27/14/13/59cb41a204354684.jpeg!600x600.jpg,直接复制到浏览器中打开就是图片了——不信试试!

    所以,我们要下载图片,其实也就是要拿到这些网址。怎么拿?正则表达式,华丽登场!

    就比如,我们如果打开了图集“窗外繁华盛开”,那就可以直接爬取图集中图片的地址了,这一个图集就搞定了。如果我们贪得无厌,想要下载更多图集的图片怎么办?(请依次打开图集,然后把鼠标放在图片上,右键图片另存为——啊,当然是开玩笑的了,毕竟我这么懒!)

    所以呢,我们还要获取所有图集的网址。基本思路就是:打开一个图集网址——获取图片链接——图片下载——打开下一个图集网址——(这不是废话吗?)

    那么,如何获取所有图集网址呢?

    其实,我们第一次查看源代码的时候提到,好像已经看到了图集的名称,是的,图集的名称,再回头去看看,里面的确已经包含了图集的网址和名称了。举个栗子:

    <h5><a href="/haokan/dongman/1349139.html" target="_blank">窗外繁花盛开</a></h5>

    这一行里,/haokan/dongman/1349139.html这部分对应的就是网址,名称自己看。

    好了,和获取图片网址一样,爬呗,反正我们有个不怕累的虫子(啊?虫子又是什么?我是谁?我在哪里?我在干什么?)

    现在我们看到的是第一页,如果我们还想下载第二页、第三页、...所有页面的图集怎么办?(下载了有啥用?大概有病)

    看来我们只好手动一个一个页面的打开,然后“放虫咬图”!(pi~)

    好吧,还是偷懒一下好了。反正我们就是下载Q乐园(高端大气上档次!)中的动漫图片,我们发现它的网页都是有规律的:比如第一页的网址:http://www.qzone.cc/haokan/dongman/,第二页的网址:http://www.qzone.cc/haokan/dongman/list_2.html。我猜第三页的网址是:http://www.qzone.cc/haokan/dongman/list_3.html(麻德,我好聪明怎么办?!)

    于是网址我们可以通过列表的方式构造了。(列表!终于听到了一个正常的词儿,但其实我,根本没用到好吗啊啊啊啊)

    所以,思路很简单了,我们先构造所有页面的网址集合,对每个页面网址爬取该页面上图集的网址,然后从图集的网址上爬取该图集包含的图片的网址,然后下载图片。(感觉好轻松!其实就是好轻松)

    有几个小tips:

    1.我不想把所有图片都扔到一个文件夹中,我想按照图集的名称分别创建文件夹,然后分别保存。怎么办?爬取图集名称创建文件夹呗~

    2.图集名称中包含特殊字符,创建文件夹时很可能会因命名问题出错,那么怎么办?随便吧。。。我就随便一搞,差不多就行。

    3.我发现页面源代码中没有包含一共多少页面,那么我们怎么判断一共要抓去多少页面呢?我猜大概不会出现http://www.qzone.cc/haokan/dongman/list_10000.html,一万页,这渣网,下到啥时候啊。嗯,还是随便吧,我就是随便一搞,真的差不多就行

    4.如果有一张图片,或者有一个网页卡了,就是下载不下来或者打不开了怎么办?随便搞搞吧,定个时间,没反应劳资还不看了,跳过!

    5.如果图集重复了,我想下载到同一个文件夹中,还不想覆盖原有的图片怎么办?我猜你肯定知道随便搞搞就行,你比我聪明!

    6.我忘记了...

    看我“自由派”的代码吧,大概会编程的人都受不了,框架结构什么的随便了,反正我乐意(斜眼)。直接跳过V1.0,V2.0,看V3.0吧!(建议V3.0也不用看,啥用啊)

    V1.0

    #Q乐园图片下载
    
    #载入模块:路径设置、爬虫、正则表达式
    import os
    import urllib
    import re
    
    #定义函数
    #页面抓取函数
    def getHTML(url, dec):
        html = urllib.request.urlopen(url).read()
        html = html.decode(dec)
        return html
    
    #网页列表获取
    def HtmlToList(html, s):
        pat = re.compile(s)
        ToList = pat.findall(html)
        return ToList
        
    #页面执行函数(图片下载)
    def getIMG(url, path, name):
        imgpath = path+name+'.jpg'
        print('    正在下载第%s张照片...'%name)
        urllib.request.urlretrieve(url, imgpath)
    
    
    
    #自定义创建文件夹的函数
    def makeDir(path, name):
        topath = path+name
        flag = False
        if not os.path.isdir(topath):
            os.mkdir(topath)
            print('创建文件夹:%s!'%name)
        else:
            flag = True
        topath = topath+'\'
        return topath,flag
    
    #初始页面(第一页)网址
    url = r'http://www.qzone.cc/haokan/dongman/'
    
    #正则表达式:匹配每页上的图集网址
    SetS = r'<h5><a href="/.+?/.+?/(.+?.html)" target="_blank">(.+?)</a></h5>'
    
    #获取页面上图集网址集合
    html = getHTML(url, 'UTF-8')
    PicSetlist = HtmlToList(html, SetS)
    
    #文件夹准备
    path = 'D:\QLeYuan\'
    name = 'PicSet'
    
    #正则表达式:在图集网页中匹配图片
    PicS = r'original="(http://.+?/.+?/.+?/.+?/.+?/.+?/.+?.jpg)" class="lazy"'
    #第一页图集下载
    for bit,dirname in PicSetlist:
        #创建图集路径文件夹
        dirname.replace('?','')
        dirpath = path+name+'\'
        filepath,flag = makeDir(dirpath, dirname)
        #组合图集url
        seturl = url+bit
        #获取图片列表
        html = getHTML(seturl, 'UTF-8')
        PicList = HtmlToList(html, PicS)
        #图片名称
        imgname = 0
        for PicUrl in PicList:
            #如果获取的图集名称重复,那么下载到同一文件夹中并重命名,避免出现同名文件无法创建的问题
            if flag:
                picname = '1-'+str(imgname)
            else:
                picname = str(imgname)
            #获取图片
            getIMG(PicUrl, filepath, picname)
            imgname = imgname+1

    V2.0

    #Q乐园图片下载
    
    #载入模块:路径设置、爬虫、正则表达式
    import os
    import urllib
    import re
    
    #设置超时处理
    import socket
    
    #定义函数
    #页面抓取函数
    def getHTML(url, dec):
        html = urllib.request.urlopen(url).read()
        html = html.decode(dec)
        return html
    
    #网页列表获取
    def HtmlToList(html, s):
        pat = re.compile(s)
        ToList = pat.findall(html)
        return ToList
        
    #页面执行函数(图片下载)
    def getIMG(url, path, name):
        imgpath = path+name+'.jpg'
        urllib.request.urlretrieve(url, imgpath)
        
    #自定义创建文件夹的函数
    def makeDir(path, name):
        topath = path+name
        flag = False
        if not os.path.isdir(topath):
            print('创建文件夹:%s!'%dirname)
            os.mkdir(topath)
        else:
            flag = True
        topath = topath+'\'
        return topath,flag
    
    #初始页面(第一页)网址
    url_1 = r'http://www.qzone.cc/haokan/dongman/'
    
    #文件夹准备
    path = 'D:\QLeYuan\'
    name = 'PicSet'
    #正则表达式:匹配每页上的图集网址 
    SetS = r'<h5><a href="/.+?/.+?/(.+?.html)" target="_blank">(.+?)</a></h5>' 
    #正则表达式:匹配所有页面网址 
    UrlS = r'<a href="/.+?/.+?/(.+?.html)">.</a></li>' 
    #获取页面网址 
    html = getHTML(url_1, 'UTF-8') 
    UrlList = HtmlToList(html, UrlS) 
    #构造第一页的网址 
    UrlList.insert(0,'') 
    for root in UrlList: 
        url = url_1+root 
        #获取页面上图集网址集合 
        html = getHTML(url, 'UTF-8') 
        PicSetList = HtmlToList(html, SetS) 
        #正则表达式:在图集网页中匹配图片 
        PicS = r'original="(http://.+?/.+?/.+?/.+?/.+?/.+?/.+?.jpg)" class="lazy"' 
        #第一页图集下载 
        for bit,dirname in PicSetList: 
            #创建图集路径文件夹 
            dirname = dirname.replace('?','') 
            dirname = dirname.replace('\','') 
            dirpath = path+name+'\' 
            filepath,flag = makeDir(dirpath, dirname) 
            #组合图集url 
            seturl = url_1+bit 
            #获取图片列表 
            html = getHTML(seturl, 'UTF-8') 
            PicList = HtmlToList(html, PicS) 
            #图片名称 
            imgname = 0 
            for PicUrl in PicList: 
                #如果获取的图集名称重复,那么下载到同一文件夹中并重命名,避免出现同名文件无法创建的问题 
                if flag: 
                    picname = '1-'+str(imgname) 
                else: 
                    picname = str(imgname) 
                    #获取图片:如果遇到下载异常会提示 
                try: 
                    #下载超时会报错跳过该异常下载其他 
                    socket.setdefaulttimeout(5.0) 
                    print(' 正在下载第%s张照片...'%picname) 
                    getIMG(PicUrl, filepath, picname) 
                except: 
                    print('图片%d下载异常'%imgname) 
                    imgname = imgname+1 
                    print('下载完成!')

    V3.0

    #Q乐园图片下载
    
    #载入模块:路径设置、爬虫、正则表达式
    import os
    import urllib
    import re
    
    #设置超时处理
    import socket
    
    #定义函数
    #页面抓取函数
    def getHTML(url, dec):
        html = urllib.request.urlopen(url).read()
        html = html.decode(dec)
        return html
    
    #网页列表获取
    def HtmlToList(html, s):
        pat = re.compile(s)
        ToList = pat.findall(html)
        return ToList
        
    #页面执行函数(图片下载)
    def getIMG(url, path, name):
        imgpath = path+name+'.jpg'
        urllib.request.urlretrieve(url, imgpath)
        
    #自定义创建文件夹的函数
    def makeDir(path, name):
        topath = path+name
        flag = False
        if not os.path.isdir(topath):
            print('创建文件夹:%s!'%dirname)
            os.mkdir(topath)
        else:
            flag = True
        topath = topath+'\'
        return topath,flag
    
    #检查文件夹名是否合法
    def checkDirName(name=None):
        if name is None:
            print('name is None.')
        s = r'[;\/:*?"<>|
    ]+'
        pat = re.compile(s)
        bug = pat.findall(name)
        if bug:
            for char in bug:
                name = name.replace(char, '_')    
        return name
        
    #初始页面(第一页)网址
    url_1 = r'http://www.qzone.cc/haokan/dongman/'
    url = url_1
    
    #文件夹准备
    path = 'D:\QLeYuan\'
    name = 'PicSet'
    #正则表达式:匹配每页上的图集网址
    SetS = r'<h5><a href="/.+?/.+?/(.+?.html)" target="_blank">(.+?)</a></h5>'
    
    #图集名称重复下载到同一文件夹
    namesame = 1
    
    label = True
    root = 2
    
    while label:
        try:
        #获取页面上图集网址集合
            html = getHTML(url, 'UTF-8')
            PicSetList = HtmlToList(html, SetS)
        except:
            print('下载所有页面已下载完成!或者打开网址出错!')
            break
        #正则表达式:在图集网页中匹配图片
        PicS = r'original="(http://.+?/.+?/.+?/.+?/.+?/.+?/.+?.jpg)" class="lazy"'
        #第一页图集下载
        print('正在下载第%d页图集:'%(root-1))
        for bit,dirname in PicSetList:
            #创建图集路径文件夹
            dirname = checkDirName(dirname)
            dirpath = path+name+'\'
            filepath,flag = makeDir(dirpath, dirname)
            #组合图集url
            seturl = url_1+bit
            #获取图片列表
            html = getHTML(seturl, 'UTF-8')
            PicList = HtmlToList(html, PicS)
            #图片名称
            imgname = 0
            if flag:
                prename = str(namesame)+'_'
                namesame = namesame+1
            else:
                namesame = 1
                prename = ''
                    
            for PicUrl in PicList:
                #如果获取的图集名称重复,那么下载到同一文件夹中并重命名,避免出现同名文件无法创建的问题 
                picname = prename+str(imgname)
                    #获取图片:如果遇到下载异常会提示 
                try:
                    #下载超时会报错跳过该异常下载其他 
                    socket.setdefaulttimeout(5.0)
                    print(' 正在下载第%s张照片...'%picname)
                    getIMG(PicUrl, filepath, picname)
                except:
                    print('图片%d下载异常'%imgname)
                    
                
                imgname = imgname+1
        #更新网址
        url = url_1+'list_'+str(root)+'.html'
        root = root+1 

    (可以搞一搞,不止下载动漫图片,下载所有的类型的图片,不难实现。实在没有什么意思了...)

    那么,下载了图集长什么样子呢?

    先看下下载过程大概长什么样子(其实根本没有过程):

    下载后部分文件夹:

    看看“窗外繁华盛开”,图片是什么样子:

    我没有实际运行到最后结束(毕竟渣网速)。我尝试不实际下载图片,只看共有多少个图集,大概有两三千不是问题,平均一个图集5张图片的话,一万张图片都是妥妥的。

    好像压根没有说到正则表达式是什么,爬虫是什么,实现技巧是什么...别问我,反正我也不知道是什么。还有,别问我是什么浏览器,因为这并不重要,反正什么浏览器都行(白眼)

    千万不要把这当做是教程,这大概只是理科生的一篇“随笔”,吐槽一下近期的部分心情(强调是部分!)。开心就好啊~

    最后,正经说一句:如有侵权,请联系删除!(麻德,我侵了谁的权,惊恐)

  • 相关阅读:
    安全意识第二期丨小失误酿大祸,上班族请注意啦
    安全意识第一期丨网购退款失败,导致财、物两空?
    CTF挑战赛丨网络内生安全试验场第一季答题赛火热开启
    挑战世界级“人机大战”,更有万元奖金等你来拿
    【Web安全入门】三个技巧教你玩转XSS漏洞
    【新手篇】搭建DCN漏洞靶机及简单的SQL手工注入
    想入门Web安全,这些基础知识都学会了吗?
    CTF必备技能丨Linux Pwn入门教程——PIE与bypass思路
    大学生网络安全竞赛开始报名啦
    「黑客必备技能」Python正则表达式详解
  • 原文地址:https://www.cnblogs.com/dennis-liucd/p/7576383.html
Copyright © 2011-2022 走看看