Python爬虫学习之爬美女图片

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python爬虫学习之爬美女图片相关的知识,希望对你有一定的参考价值。

  最近看机器学习挺火的,然后,想要借助业余时间,来学习Python,希望能为来年找一份比较好的工作。

  首先,学习得要有动力,动力,从哪里来呢?肯定是从日常需求之中来。我学Python看网上介绍。能通过Python来编写爬虫,于是,我也的简单的看了一下Python的介绍,主要是Python的一些语法,还有正则表达式。

好了,学习使用Python之前,来给大家看一下我们需要进行爬去的网站:技术分享

看到这个网站,感谢美女很养眼的同时,网站的图片也不太过,就是比较性感而已。看到这个多的美女,你想不想要将这些爬取到的美女,保存在你的硬盘,或者保存在你的网站,增加流量呢?

好了,目标网站有了,接下来,我们直接真刀真枪的直接开干吧。

考虑到,有很多和我一样的小白,我暂时,不介绍使用Pyspider来做爬虫,我们就使用Python的一些库来做爬虫,一步一步的进阶。

接下来需要大家安装一个IDE来编写Python脚本,我给大家推荐Pycharm编辑器。

技术分享

恩,接下来直接上代码了,做好准备了没?

第一步:解析美女类别:

技术分享

if __name__ == "__main__":
   # page = 8
    url = "http://www.mmjpg.com/"

    base_url = urlparse(url)
    #url = "http://cuiqingcai.com/1319.html"
    #menu = getallAltls(url)
    ##menu = getparAltls(url, page)

    #url = "http://www.mmjpg.com/tag/tgod"
    path =  r"E:\\image"
    #path = path + "\\\\" + "推女神"
    craw = Crawler()
    soup = craw.doc(craw.getHtml(url))
    total = 0
    for each in soup(soup(".subnav")(a[href^="http://www.mmjpg.com/tag"])).items():
        utils.log( "即将下载: " + each.text() + each.attr(href) )
        path= r"E:\\image"
        path = path + "\\\\" + each.text()
        utils.log( "即将存放在:" + path )
        total += 1
        if total<=11:
#            continue
            pass
        else:
            param={"url":each.attr(href),"path":path}
            craw.downimgofsite(param )

 

第二步:下载站点某图集下的所有图片:

 def downimgofsite(self , param):

        url = ""
        path = ""
        #path = str(path)
        if param and "url" in param:
            url = param["url"]
            utils.log( "即将下载:" + url)
        else:
            utils.log( "线程运行错误,url为空")
            return

        if param and "path" in param:
            path = param["path"]
            utils.log( "即将保存路径:" + path)
        else:
            utils.log( "线程运行错误,路径为空" )
            return

        #获取所有图集的名称和链接
        meun_list = self.getallAltls(url)
        total = 0
        directorypath = ""

        #print os.getcwd()

        try:
            for meun in meun_list:
                try:
                    directoryname = self.str_fomat(meun[0])
                    if not directoryname:
                        utils.log("获取到的图集为空" + str(directoryname))
                        continue
                    if path.strip() != "":
                        directorypath = path + "\\\\" + directoryname
                    else:
                        directorypath = os.getcwd() + "\\\\" + directoryname

                    if not os.path.exists(directorypath):
                        os.makedirs(directorypath)
                        utils.log( "图集 "+ meun[0]+ " 创建路径:" + directorypath )

                    utils.log("正在下载第 "+ str(total) + "个图集:" + meun[0] + " 链接:" + url)
                    result = self.getSinglePic(meun[1], directorypath)
                    total += 1
                except IOError, param:
                    utils.log("图集:"+ meun[0] +"IO读写错误,原因"+ param)
                    continue
                except BaseException,param:
                    utils.log("图集:"+ meun[0] + "产生意外错误")
                    continue
                except:
                    utils.log("图集:"+ meun[0] + "产生意外错误,原因:" + param)
                    continue

                try:
                    if result:
                        utils.log( "图集:" + meun[0] + " 获取链接:" + meun[1] +" 成功,共下载:" + str(result) + " 张图片" )
                    else:
                        os.rmdir(directorypath)
                        utils.log( "图集:" + meun[0] + " 获取链接:" + meun[1] +" 失败,即将删除目录:" + directoryname )
                    #self.cleanDir(directorypath)
                except WindowsError,parm:
                    utils.log( "操作目录:"+ directoryname + "失败,原因:"+ parm ,logging.ERROR)
                    continue
                except BaseException,parm:
                    utils.log( "发生错误,错误原因:"+ parm ,logging.ERROR)
                    continue
                except:
                    utils.log( "发生未知错误" ,logging.ERROR)
                    continue
        except BaseException,parm:
            utils.log( "下载站点图片出错,错误原因:" + parm ,logging.ERROR)

获取所有图集:

 #function获取所有的图集名称
    def getallAltls(self,url):
        html =self.getHtml(url)
        if not html:
            utils.log("获取网页:"+ url +"错误,错误原因:没有获取到网页")
            return None
        soup = self.bfs(html)
        totalpage = int(self.getPageNum(html ,url))
        meun = self.getPicNameandLink(url)
        album_id = re.search( r\\d+, url, re.M|re.I)
        if not album_id:
            album_id = str(int(random.random() * 10000))
        albm_url = url
        album_create_time =  time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        album_name = soup.find("div",class_="current").find("i").string

        #循环遍历所有的图集页面,获取图集名称和链接
        for pos in range(2,totalpage+1):
            currenturl = url + "/" + str(pos)
            #getPicNameandLink()返回的值是一个list。
            #当一个list插入到另一个list中时,使用extend。
            #若是插入一个值时,可以用append
            tmenu = self.getPicNameandLink(currenturl)
            if  tmenu:
                meun.extend(tmenu)
                utils.log("从链接:" + url +"获取到" + str(len(tmenu)) + "链接")
            else:
                utils.log("获取链接:"+ url + "图集失败")
            # url = nextpage = self.getNextPage(url)
            # meun.extend(self.getPicNameandLink(nextpage))

        return meun

 

获取整个图集的所有页码:

# 获取整个图集的页码
    def getPageNum(self , html , url):
        soup = self.bfs( html)
        # 直接在站点首页获取所有图集的总页码
        #nums=soup.find_all(‘a‘,class_=‘page-numbers‘)
        # 除掉“下一页”的链接,并获取到最后一页
        #totlePage = int(nums[-2].text)
        p = r共\\d+?页
        #print soup.get_text()
        pa = re.compile(p.encode(utf-8))
        match = re.search(pa, soup.get_text().encode("utf-8"))
        if match:
            ct = re.sub(r\\D,‘‘, match.group(0))
            if not ct:
                 utils.log( "链接: "+ url + " 页面共:" +"0" +  "页,总页面查找失败" )
                 return 1
            utils.log( "链接: "+ url + " 页面共:" + str(ct) +  "")
            totlePage = int(ct)
            print totlePage
            return totlePage
        else:
            utils.log( "链接: "+ url + " 页面共:" +"0" +  "页,总页面查找失败" )
            return 1

获取指定图集下图集名称和链接:

#获取指定页面下图集名称和链接
    def getPicNameandLink(self , url):
        html = self.getHtml(url)
        if html:
            soup = self.bfs( html)
        else:
            utils.log("链接:" + url + " 请求失败" + "网页:")
            utils.log(str(html))
            return  None

        soup = self.bfs(html)
        meun = []
        total = 1
        link_list = soup.find("div", class_="pic").find_all(a ,target="_blank")  #+ soup.find_all(‘img‘ ,target="_blank")
        #print type(link_count)
        link_count = len(link_list)
        #print type(link_count)
        utils.log("在链接:"+ url+ "下找到: "+ str(link_count) + " 链接")
        if(link_count > 0):
            for pic in link_list:
                link = pic["href"]
                self.links.append(link)
                picturename = ""
                img = pic.find("img")
                if img:
                    # 保证中文字符能够正常转码。
                    picturename = unicode(str(img["alt"]))
                    self.title.append(picturename)
                else:
                    continue
                    #插入图集名称和对应的url
                meun.append([picturename,link])
                ids=self.get_url_page(url)
                if ids:
                    self.ids.append(ids)
                else:
                    self.ids.append(total)
                    total += 1
            utils.log( "在链接:" + url +" 下实际找到:" + str(len(meun)) + "个链接")
            return meun
        else:
            return None

获取下一页:

#获取下一页的链接
    def getNextPage(self , url):
         base_url = urlparse(url)
         html = self.getHtml(url)
         if html:
            soup = self.bfs( html)
         else:
            utils.log("链接:" + url + " 请求失败" + "网页:")
            utils.log(html)
            return  None

         nt = "下一页"
         next_url = soup.find_all(a,text=nt)
         ret_url= next_url[0][href]
         #print ret_url
         if ret_url:
             try:
                 if re.match(r^https?:/{2}\\w.+$, ret_url):
                     utils.log( "获取到正确的网址:" + ret_url)
                     return ret_url
                 else:
                    ret_url = base_url.scheme +"://"+ base_url.netloc + next_url[0][href]
                    utils.log("只获取到查询路径,处理之后网址为:"+ ret_url)
                    return ret_url
             except BaseException, Argument:
                 utils.log("查找下一页出错,错误为:"+Argument ,logging.ERROR)
                 return  None
         else:
            print "获取下一页地址失败!"
            return None

第三部:获取某一个妹子的所有图片:

技术分享

   #下载单个相册中的所有图片
    def getSinglePic(self , url , path):
        title = re.split(r\\\\, path)
        title = title[-1]
        try:
            page_url = self.getSinglePicUrl(url)
            if page_url:
                totalPageNum = self.getSinglePicTotal(url)
                base_url = urlparse(url)
                real_url =base_url.scheme+"://"+base_url.netloc
                #从第一页开始,下载单个图集中所有的图片
                #range()第二个参数是范围值的上限,循环时不包括该值
                #需要加1以保证读取到所有页面。

                p = r.+\\/
                pa = re.compile(p)
                #print  title

                if totalPageNum:
                    for i in range(1,totalPageNum + 1):
                        currenturl = real_url + "/" + str(i)
                        self.downloadpic(currenturl,path)

                else:
                    next_url = self.getSinglePicUrl(url)
                    cur_page = 1
                    utils.log("即将下载图集:" + title)
                    while next_url:
                        match = re.search(pa, next_url).group(0)
                        if match:
                            currenturl = real_url+ "/" + match  + str(cur_page)
                        else:
                            currenturl = real_url+ "/" + next_url    # + str(cur_page)
                        #utils.log("正在下载: "+ str(cur_page) + " 个图片:"  +" 链接:"+ url )
                        self.downloadpic(currenturl,path)
                        cur_page += 1
                        next_url = self.getSinglePicUrl(currenturl)          #判断是否还有下一页

                        # if cur_page > 2:
                        #     return  cur_page

                return (cur_page-1)
            else:
                utils.log( "图集:"+ title+ "链接:" + url +" 获取图片链接失败")
                return None
        except BaseException,param:
            utils.log( "下载单个相册:" + title + " 链接:" + url+  "中的所有图片异常,原因:" + param ,logging.ERROR)
            return None
        except:
            utils.log(  "下载单个相册:" + title +  " 链接:" + url+ "中的所有图片异常"  ,logging.ERROR)
            return  None
 #获取单个相册内图片链接
    def getSinglePicUrl(self , url):
        html = self.getHtml(url)
        if html:
            soup = self.bfs( html)
        else:
            utils.log("链接:" + url + " 请求失败" + "网页:")
            utils.log(html)
            return  None

        try:
            if soup:
                #print "当前页面链接:"+ url
                nt = "下一张"
                next_url = soup.find_all(a,text=nt)
                if next_url:
                    ret_url= next_url[0][href]
                else:
                    return None
            else:
                utils.log( "网页" + url + "读取失败")
                return None
        except BaseException,param:
            utils.log( "获取单个相册内图片链接异常,原因" + param ,logging.ERROR)
            return  None

        return ret_url

获取图片数量:

 #获取单个相册内图片所有图片的数量
    def getSinglePicTotal(self , url):
        html = self.getHtml(url)
        if html:
            soup = self.bfs( html)
        else:
            utils.log("链接:" + url + " 请求失败" + "网页:")
            utils.log(html)
            return  None
        #pagenavi还是一个对象(Tag),可以通过find_all找出指定标签出来
        #print "当前页面链接:"+ url

        if soup:
            #print "获取链接:"+url +" 成功"
            pass
        else:
            utils.log("获取链接:"+url +" 失败")
            return None

        nt = "全部图片"
        try:
            total = soup.find_all(a,text=nt)
            if total:
                total= re.sub(\\D,"",total[0][href])
            else:
                total = 0
        except BaseException,param:
            utils.log( "获取单个相册内图片所有图片的数量异常,原因" + param , logging.ERROR)
            return  None

        return total

第四步:下个单个相册的所有图片:

 

    #下载单个相册中的所有图片
    def getSinglePic(self , url , path):
        title = re.split(r\\\\, path)
        title = title[-1]
        try:
            page_url = self.getSinglePicUrl(url)
            if page_url:
                totalPageNum = self.getSinglePicTotal(url)
                base_url = urlparse(url)
                real_url =base_url.scheme+"://"+base_url.netloc
                #从第一页开始,下载单个图集中所有的图片
                #range()第二个参数是范围值的上限,循环时不包括该值
                #需要加1以保证读取到所有页面。

                p = r.+\\/
                pa = re.compile(p)
                #print  title

                if totalPageNum:
                    for i in range(1,totalPageNum + 1):
                        currenturl = real_url + "/" + str(i)
                        self.downloadpic(currenturl,path)

                else:
                    next_url = self.getSinglePicUrl(url)
                    cur_page = 1
                    utils.log("即将下载图集:" + title)
                    while next_url:
                        match = re.search(pa, next_url).group(0)
                        if match:
                            currenturl = real_url+ "/" + match  + str(cur_page)
                        else:
                            currenturl = real_url+ "/" + next_url    # + str(cur_page)
                        #utils.log("正在下载: "+ str(cur_page) + " 个图片:"  +" 链接:"+ url )
                        self.downloadpic(currenturl,path)
                        cur_page += 1
                        next_url = self.getSinglePicUrl(currenturl)          #判断是否还有下一页

                        # if cur_page > 2:
                        #     return  cur_page

                return (cur_page-1)
            else:
                utils.log( "图集:"+ title+ "链接:" + url +" 获取图片链接失败")
                return None
        except BaseException,param:
            utils.log( "下载单个相册:" + title + " 链接:" + url+  "中的所有图片异常,原因:" + param ,logging.ERROR)
            return None
        except:
            utils.log(  "下载单个相册:" + title +  " 链接:" + url+ "中的所有图片异常"  ,logging.ERROR)
            return  None
            

下载图片的重点来了:

 

    #下载单个相册中的所有图片
    def getSinglePic(self , url , path):
        title = re.split(r\\\\, path)
        title = title[-1]
        try:
            page_url = self.getSinglePicUrl(url)
            if page_url:
                totalPageNum = self.getSinglePicTotal(url)
                base_url = urlparse(url)
                real_url =base_url.scheme+"://"+base_url.netloc
                #从第一页开始,下载单个图集中所有的图片
                #range()第二个参数是范围值的上限,循环时不包括该值
                #需要加1以保证读取到所有页面。

                p = r.+\\/
                pa = re.compile(p)
                #print  title

                if totalPageNum:
                    for i in range(1,totalPageNum + 1):
                        currenturl = real_url + "/" + str(i)
                        self.downloadpic(currenturl,path)

                else:
                    next_url = self.getSinglePicUrl(url)
                    cur_page = 1
                    utils.log("即将下载图集:" + title)
                    while next_url:
                        match = re.search(pa, next_url).group(0)
                        if match:
                            currenturl = real_url+ "/" + match  + str(cur_page)
                        else:
                            currenturl = real_url+ "/" + next_url    # + str(cur_page)
                        #utils.log("正在下载: "+ str(cur_page) + " 个图片:"  +" 链接:"+ url )
                        self.downloadpic(currenturl,path)
                        cur_page += 1
                        next_url = self.getSinglePicUrl(currenturl)          #判断是否还有下一页

                        # if cur_page > 2:
                        #     return  cur_page

                return (cur_page-1)
            else:
                utils.log( "图集:"+ title+ "链接:" + url +" 获取图片链接失败")
                return None
        except BaseException,param:
            utils.log( "下载单个相册:" + title + " 链接:" + url+  "中的所有图片异常,原因:" + param ,logging.ERROR)
            return None
        except:
            utils.log(  "下载单个相册:" + title +  " 链接:" + url+ "中的所有图片异常"  ,logging.ERROR)
            return  None
            

 

第五步:下载图片:

    def Schedule(a,b,c):
        ‘‘‘‘‘
        a:已经下载的数据块
        b:数据块的大小
        c:远程文件的大小
       ‘‘‘
        per = 100.0 * a * b / c
        if per > 100 :
            per = 100
        print %.2f%% % per
        
    def auto_down(self, url , filename):
        file_dir = os.path.split(filename )[0]
        if os.path.isdir(file_dir):
            pass
        else:
            utils.log("目录:" + file_dir +"不存在,将重新创建该目录,用于下载文件:"+ filename)
            os.makedirs(file_dir)
        urllib.urlretrieve(url,filename ,Schedule)

接下来需要判断,图片是否存在,以及删除文件为空的文件夹:

#判断文件是否存在
    def file_exists(self,filename):
        try:
            with open(filename) as f:
                return True
        except IOError:
            return False

  #删除空目录
    def cleanDir( dir ):
        try:
            if os.path.isdir( dir ):
                files = os.listdir(dir)  # 获取路径下的子文件(夹)列表
                if files:
                    utils.log( "找到:" +dir+"下共:" + str(len(files)) +" 文件或文件夹")
                else:
                    dir= dir+"\\\\"
                    files = os.listdir(dir) # 获取路径下的子文件(夹)列表
                    utils.log( "找到:" + dir  +"" +str(len(files)) +"文件或文件夹")
                for file in files:
                    print 扫描路径:+ file.decode(GBK)
                    if os.path.isdir(file):  # 如果是文件夹
                        if not os.listdir(file):  # 如果子文件为空
                            os.rmdir(file)  # 删除这个空文件夹
                            utils.log( file.decode(GBK) + " 文件夹为空,即将删除" )
                    elif os.path.isfile(file):  # 如果是文件
                        if os.path.getsize(file) == 0:  # 文件大小为0
                            os.remove(file)  # 删除这个文件
                            utils.log( file.decode(GBK)+"文件为空,即将删除" )
        except BaseException,param:
            utils.log( "扫描路径"+ dir + "异常,原因:" + str(param) ,logging.ERROR )
        utils.log( "扫描路径"+ dir + " 结束")

 好了,大工告成,让我们取旁边喝一杯,稍微等一会,就有大大的惊喜。

技术分享

好了,这次的分享,到这里结束了,完整的源代码大家可以加入QQ群: 98556420,获取。

下一期,我也将会和大家分享使用人脸识别,来识别这些妹子。。。

以上是关于Python爬虫学习之爬美女图片的主要内容,如果未能解决你的问题,请参考以下文章

爬虫概念与编程学习之如何爬取视频网站页面(用HttpClient)

爬虫概念与编程学习之如何爬取网页源代码

Python练习册 第 0013 题: 用 Python 写一个爬图片的程序,爬 这个链接里的日本妹子图片 :-),(http://tieba.baidu.com/p/2166231880)(代码片段

python爬虫学习之使用XPath解析开奖网站

python学习之爬虫 ——————爬取网易云歌词

Python学习之爬虫