一、爬虫实战,40G PPT文档轻松拿

作者: 北塔资讯 | 来源:发表于2017-10-27 16:29 被阅读618次

    因为需要较多的ppt文档,爬了一个网站 www.1ppt.com。本文主要是记录这一过程,如果您正在做文档爬虫,或者是MSOffice文档分析,这系列对您可能有些帮助。

    本文的主要内容是:

    • 简单介绍1ppt.com的爬取逻辑;
    • pptSpider源码讲解;

    1.简单介绍1ppt.com的爬取逻辑

    站点分析
    分析1ppt.com 并不复杂,站点的结构也很简单,它的页面结构如下:

    1ppt 三级目录

    就是个三级目录,没有什么难点,
    接下来我分三步来介绍这个过程。

    第一步、根据首页,获取板块分页目录;
    第二步、遍历板块中的所有详情页连接 ;
    第三步、获取文档信息;

    1.1、根据首页,获取板块分页目录

    1ppt.com的页面布局是这样的:

    分类目录

    获取它的分页目录,不管是描述还是连接,都很方便。

    注意className

    通过浏览器,CopyXPath能得到:

    /html/body/div[5]/dl[1]/dd/ul[1]/li[2]/h4/a
    

    精简一下语法,标题和描述的定位方法可以写成:

    self.m_PageListDes = selector.xpath('//dd[@class="ikejian_col_nav"]/ul/li/h4/a/@title')
    self.m_PageListURL = selector.xpath('//dd[@class="ikejian_col_nav"]/ul/li/h4/a/@href')
    

    自此,我们已经能拿到这个网站的所有分类目录。

    1.2、遍历板块中的所有详情页连接

    详情页连接

    详情页也不难抓,”arclist“下就是详情页信息的集合。同时,所有页面的遍历方法可通 过"下一页"button来判断。如果有这个按钮,就一直找下去,所有详情页就能找全了。

    遍历逻辑,nextPage

    需要注意的是,这个站点绝大多数的页面都是这个样式,但也有不同的,做好返回值的判断。

    1.3、获取文档信息

    详情页信息主要是两部分,文件描述和下载地址。

    文件描述的信息有:

    docInfo info_left

    下载地址是:


    downUrlList

    2、pptSpider源码讲解

    总的来说,爬这个站点是很简单的,没有太多的动态信息,都是明码。找对逻辑,依次抓就是了。

    我拿到了这个站点的所有文档,其实也没多少,3万多ppt,不到40G。
    我已经把整理好的源码传到git,地址为:https://github.com/northtower/pptSpider
    感谢大家Star!!

    # -*- coding:utf8 -*-
    
    import requests
    import os
    from lxml import etree
    from requests.exceptions import ReadTimeout,ConnectionError,RequestException
    
    LOCALPATH = "/Users/Sophia/Codes/python/spider/pptDownLoad/"
    HOMEPAGE  = 'http://www.1ppt.com'
    
    '''
    简单封装了ppt1.com单站爬虫的分步功能,大体上分三个步骤:
    1、根据首页,获取板块分页目录  GetIndexPage();
    2、遍历板块中的所有文档内容   GetContentByURL;
    3、获取文档信息             GetDocInfo
    
    扩展功能1:提供文件下载功能   DownLoadFile
    '''
    class CPPT1Spider():
        def __init__(self , homePage):
            self.initWithHomePage(homePage)
        
        def initWithHomePage(self , oHomePage):
            print ""
            html = requests.get(oHomePage)
            html.encoding = 'gb2312'
            selector = etree.HTML(html.text)
    
            self.m_PageListDes = selector.xpath('//dd[@class="ikejian_col_nav"]/ul/li/h4/a/@title')
            self.m_PageListURL = selector.xpath('//dd[@class="ikejian_col_nav"]/ul/li/h4/a/@href')
    
        #根据首页,获取板块目录。在ppt1网站中,板块目录就是初【出版社->年级教材】
        def GetIndexPage(self):   
            oCounts = 1             
            for value1,value2 in zip(self.m_PageListDes ,self.m_PageListURL):
                oListPageURL = HOMEPAGE + value2
                createPath = LOCALPATH + value1
                print "[", oCounts, "]", value1, oListPageURL
                oCounts = oCounts + 1        
                self.GetContentByURL(oListPageURL , createPath) 
                #if not os.path.exists(createPath):
                    #os.mkdir(createPath)
                    #PS_getContentPage.GetContentByURL(oListPageURL , createPath)
                #print createPath
    
        #根据板块首页,遍历所有详情页
        def GetContentByURL(self , oListPageURL , oLocalPath):
    
            homePage = "http://www.1ppt.com"
            html = requests.get(oListPageURL)
            html.encoding = 'gb2312'
            selector = etree.HTML(html.text)
    
            # listPage 的获取办法
            content3 = selector.xpath('//ul[@class="arclist"]/li/a/@href')
            for value in content3:
                listPageUrl = homePage + value
                self.GetDocInfo(listPageUrl)
                #oRet = PS_downloadFile.downLoadByURL(listPageUrl , oLocalPath)
                
            #have nextpage 通过“下一页”的关键字查找
            content4 = selector.xpath(u"//a[contains(text(), '下一页')]")
            for value in content4:
                strlistUrl = value.get('href')
                #herf绝对路径的方法没找到,就用字符串拼吧
                op = oListPageURL.rfind('.')
                if (op > 0):
                    op1 = oListPageURL.rfind('/') + 1
                    strRet = oListPageURL[:op1]
                    strRet = strRet.lower()
                    oListPageURL = strRet
    
                nextPage = oListPageURL + strlistUrl
                print "next Page -----------------------"
                print nextPage
                self.GetContentByURL(nextPage , oLocalPath)
        
        #根据详情页地址,获取文档信息。ppt1中的docInfo有很多,我只取了其中三项。
        def GetDocInfo(self , oUrl):
            html = requests.get(oUrl)
            html.encoding = 'gb2312'        
            selector = etree.HTML(html.text)
            zipUrl  = selector.xpath('//ul[@class="downurllist"]/li/a/@href')
            if not zipUrl:
                return  False
    
            print "课件详情页:" ,oUrl     
            strZip = str(zipUrl[0])
            print "课件地址:" ,strZip
            #下载文件
            #oRet = self.DownLoadFile(strZip)
    
            #频道地址
            #docInfoList  = selector.xpath('//div[@class="info_left"]/ul/li[1]/a/@href')
    
            #课件名称
            docInfoList  = selector.xpath('//div[@class="ppt_info clearfix"]/h1/text()')
            if docInfoList:
                print "课件名称:" , docInfoList[0]
            
            print ""
        
        def DownLoadFile(self, oFileURL):
    
            #模拟报文头
            oHeader = { "Accept":"text/html,application/xhtml+xml,application/xml;",
                    "Accept-Encoding":"gzip",
                    "Accept-Language":"zh-CN,zh;q=0.8",
                    "Referer":"http://www.1ppt.com/",
                    "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36"
                    }
    
            PDFName = self.GetFileNameByURL(oFileURL)
            localPDF = LOCALPATH + PDFName
    
            try:
                response = requests.get(oFileURL,headers = oHeader ,timeout=10)
                print(response.status_code)
                print localPDF
    
                if not os.path.exists(localPDF):
                    oFile = open(localPDF, "wb")
                    for chunk in response.iter_content(chunk_size=512):
                        if chunk:
                            oFile.write(chunk)
                else:
                    print "had download file:" ,localPDF
    
                return True
            except ReadTimeout:
                print("timeout")
            except ConnectionError:
                print("connection Error")
            except RequestException:
                print("error")
    
            return False
    
        def GetFileNameByURL(self, oURL):
            op = oURL.rfind('/')
            if (op > 0):
                op = op + 1
                strRet = oURL[op:]
                strRet = strRet.lower()
                return strRet
    
    if __name__ == "__main__":
        oHomePage = 'http://www.1ppt.com/kejian/'
        oSpider = CPPT1Spider(oHomePage)
        oSpider.GetIndexPage()
    

    注意事项:

    • 下载文档会有失败的情况,有些tryAgain即可解决;
    • 可以先爬去信息,再统一下载文档;
    • 下载后的文档未解压,这部分等到ppt文档分析时再做描述;

    备注

    爬虫不是本系列的重点,我的目的是ppt内容分析,所以,这部分的着墨并不多。如果您有疑问,可以给我留言。我一周内尽量给您回复。

    相关文章

      网友评论

        本文标题:一、爬虫实战,40G PPT文档轻松拿

        本文链接:https://www.haomeiwen.com/subject/ejfdpxtx.html