• [记录][python]python爬虫,下载某图片网站的所有图集


      

    随笔仅用于学习交流,转载时请注明出处,http://www.cnblogs.com/CaDevil/p/5958770.html

      该随笔是记录我的第一个python程序,一个爬去指定图片站点的所有图集,现在还是一个非常简陋的单线程程序。下一步是改写成多线程,虽然python多线程被诋毁得一塌糊涂。同时加上异常处理。

      近来练习python程序,仿照别人的爬虫写一个自己的爬虫来练练手。在编写的过程中遇到各种问题,中文编码、请求不到html等问题。撰写该随笔的目的是将所遇到的问题记录下来,并提供相应的解决方法。当然这些解决方法是参照其他人提供的,东抄抄西抄抄,^_^。

       先大致描述下代码过程中遇到的问题: 随笔仅用于学习交流,转载时请注明出处,http://www.cnblogs.com/CaDevil/p/5958770.html

    •  html中文解码

      虽然beautifulsoup默认的编码方式是utf-8,而且国内部分站点的编码方式是utf-8。还是需要手工设置一下中文的编码方式。

      在BeautifulSoup中手工设置编码方式如下所示

    encoding = "gb18030"
    soup = BeautifulSoup(html,from_encoding=encoding)  

      

    •  list的append和extend使用 随笔仅用于学习交流,转载时请注明出处,http://www.cnblogs.com/CaDevil/p/5958770.html

      查询相关资料,list中的append是向list插入一个值,extend则是将一个list插入另一个list中;

      若要将list1并入list2中,则使用list2.extend(list1);

      若向list中插入值的话,使用list.append(vale)

    •  beautifulsoup返回的值,可以直接查找符合条件的节点

       beautifulsoup返回的值是一颗语法树,结果与html dom结构差不多[这个地方有些保留,我目前不是太了解dom结构],通过find和find_all去查找相应的标签。前者返回一个标签的对象,后者返回list,该list的值是多个对象。

    •  将urllib.urlretrieve()尽量伪装成一个用户。

      使用 urlretrieve之前,将发送的http请求做些简单的伪装,尽量伪装成为一个用户,避免站点不响应下载请求。若不设置的话,通过wireshark,可以查看到下载请求的user-agent的值与python有关,服务器可能会将下载请求给忽略掉。同时还可以添加上referer,有些站点通过referer来判断盗链。若不设置的话,下载的图片全是防盗链提示图片。 随笔仅用于学习交流,转载时请注明出处,http://www.cnblogs.com/CaDevil/p/5958770.html

            #伪装一下下载的http请求,否则有些站点不响应下载请求。
            #不设置的话,下载请求中的user-agent为python+版本号
            urllib.URLopener.version = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36 SE 2.X MetaSr 1.0'
            #下载图片到指定目录中,保留图片在服务器上的文件名
            urllib.urlretrieve(imgurl,downloadpath)

      

      废话有些多,上代码。为了避免宣传图片站点的嫌疑,不放该站点的链接。 代码仅用于学习交流。

    import urllib2
    import io
    import random
    import urllib
    from bs4 import BeautifulSoup
    import re
    import os
    
    import sys
    reload(sys)
    sys.setdefaultencoding('utf8')
    
    def getHtml(url):
        #尽可能让爬虫显示为一个正常用户。若不设置,则发送的请求中,user-agent显示为Python+版本
        user_agent = [
            'Mozilla/5.0 (Windows NT 5.2) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/534.30',
            'Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0',
            'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET4.0E; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C)',
            'Opera/9.80 (Windows NT 5.1; U; zh-cn) Presto/2.9.168 Version/11.50',
            'Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1',
            'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET4.0E; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C)'        
        ]
        #设置网页编码格式,解码获取到的中文字符
        encoding = "gb18030"
        #构造http请求头,设置user-agent
        header = {"User-Agent":random.choice(user_agent)}
        #构造发送请求
        request = urllib2.Request(url,headers=header)
        #发送请求,获取服务器响应回来的html页面
        html = urllib2.urlopen(request).read()
        #使用beautifulSoup处理的html页面,类似dom
        soup = BeautifulSoup(html,from_encoding=encoding)
        return soup
    
    # 获取整个站点所有图集的页码
    def getPageNum(url):
        soup = getHtml(url)
        # 直接在站点首页获取所有图集的总页码
        nums=soup.find_all('a',class_='page-numbers')
        # 除掉“下一页”的链接,并获取到最后一页
        totlePage = int(nums[-2].text)
        return totlePage
    
    #获取指定页面下图集名称和链接
    def getPicNameandLink(url):
        
        soup = getHtml(url)
        meun = []
        #类似html dom对象,直接查找id为“pins”的ul标签,返回的结果是一个dom对象
        targetul = soup.find("ul",id="pins")
        if targetul:    
            #获取该ul下所有的超链接,返回值的类型是list,find_all中第二个参数表示某个指定标签的属性
            pic_list = targetul.find_all("a",target="_blank")
            if pic_list:
               # 遍历所有指定的标签a
                for pic in pic_list:
                    #获取图集的链接
                    link = pic["href"]
                    picturename = ""
                    #找到标签a中,“class”为“lazy”的img标签。
                    #find中,第二个参数表示某个指定标签的属性。
                    #在python中class是保留字,所有标签的class属性的名称为“class_”
                    img = pic.find("img",class_='lazy')
                    if img:
                        # 保证中文字符能够正常转码。
                        picturename = unicode(str(img["alt"]))
                    else:
                        continue
                    #插入图集名称和对应的url
                    meun.append([picturename,link])    
            
            return meun
        return None
    
    #function获取所有的图集名称
    def getallAltls(url):
        totalpage = getPageNum(url)
        #获取首页中所有的图集名称。首页的url和其他页面不同,没有page
        meun = getPicNameandLink(url)
        #循环遍历所有的图集页面,获取图集名称和链接
        for pos in range(2,totalpage):
            currenturl = url + "/page/" + str(pos)
            #getPicNameandLink()返回的值是一个list。
            #当一个list插入到另一个list中时,使用extend。
            #若是插入一个值时,可以用append
            meun.extend(getPicNameandLink(currenturl))
        
        return meun
        
    # 获取从首页到指定页面所有的图集名称和链接
    def getparAltls(url,page):
        meun = getPicNameandLink(url)
            
        for pos in range(2,page):
            currenturl = url + "/page/" + str(pos)
            meun.extend(getPicNameandLink(currenturl))
            
        return meun
    
    #获取单个相册内图片页码
    def getSinglePicNum(url):
        soup = getHtml(url)
        #pagenavi还是一个对象(Tag),可以通过find_all找出指定标签出来
        pagenavi = soup.find("div",class_="pagenavi")
        pagelink = pagenavi.find_all("a")
        
        num = int(pagelink[-2].text)
        return num
    
    
    #下载单个相册中的所有图片
    def getSinglePic(url,path):
        totalPageNum = getSinglePicNum(url)
        #从第一页开始,下载单个图集中所有的图片
        #range()第二个参数是范围值的上限,循环时不包括该值
        #需要加1以保证读取到所有页面。
        for i in range(1,totalPageNum + 1):
            currenturl = url + "/" + str(i)
            downloadpic(currenturl,path)
           
    #下载单个页面中的图片 
    def downloadpic(url,path):
        soup = getHtml(url)
        #找出指定图片所在父容器div
        pageimg = soup.find("div",class_="main-image")
        
        if pageimg:
            #找出该div容器中的img,该容器中只有一个img
            img = pageimg.find("img")
            #获取图片的url
            imgurl = img["src"]
            #获取图片的文件名
            restring = r'[A-Za-z0-9]+.jpg'
            reimgname = re.findall(restring,imgurl)
            
            #将图片保存在指定目录下
            path = str(path)
            if path.strip() == "":
                downloadpath = reimgname[0]
            else:
                downloadpath = path + "/" + reimgname[0]
            #伪装一下下载的http请求,否则有些站点不响应下载请求。
            #不设置的话,下载请求中的user-agent为python+版本号
            urllib.URLopener.version = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36 SE 2.X MetaSr 1.0'
            #下载图片到指定目录中,保留图片在服务器上的文件名
            urllib.urlretrieve(imgurl,downloadpath)
        
    def downimgofsite(url,path = ""):
        
        path = str(path)
        #获取所有图集的名称和链接
        meun_list = getallAltls(url)
        directorypath = ""
        
        for meun in meun_list:
            directoryname = meun[0]
            if path.strip() != "":
                directorypath = path + "/" + directoryname
            else:
                directorypath = os.getcwd + "/" + directoryname
            
            if not os.path.exists(directorypath):
                os.makedirs(directorypath)
            
            getSinglePic(meun[1], directorypath)
            
    
    if __name__ == "__main__":
       
        
       # page = 8
        url = "XXXXX"
        menu = getallAltls(url)
        #menu = getparAltls(url, page)  
        
        f = open("tsts.txt","a")
        for i in menu:
            f.write(str(unicode(i[0]))+"	"+str(i[1])+"
    ")
        f.close()
           
        
    View Code
  • 相关阅读:
    Eclipse中自动提示的方法参数都是arg0,arg1的解决方法
    eclipse 下找不到或无法加载主类的解决办法
    将博客搬至CSDN
    java接口中定义成员变量
    重写与重载
    多位数每一位个系数:个位num%10;十位num/10%10.......
    输出 n=6 的三角数字阵(JAVA基础回顾)
    二维数组的遍历之查漏补缺
    For循环打印正三角,倒三角,菱形
    JAVA的continue用法
  • 原文地址:https://www.cnblogs.com/CaDevil/p/5958770.html
Copyright © 2020-2023  润新知