首页 > 代码库 > Python爬虫学习之爬美女图片

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爬虫学习之爬美女图片