美文网首页
使用scrapy爬取四川大学公共管理学院教师信息实验报告

使用scrapy爬取四川大学公共管理学院教师信息实验报告

作者: 菜菜不太菜 | 来源:发表于2018-05-12 17:37 被阅读0次

    在参考zl、lly以及各种教程的代码后,完成了爬取教师名称、职称、专业、邮箱、图片、简介、研究成果、获奖成果、科研项目和人才培养信息的实验。具体代码可从我的github上面下载运行。

    一. 实验环境

    windows 10
    python2.7.15
    IDE:Eclipse+PyDev
    scrapy 1.5.0

    二. 实验前需安装的库

    scrapy, PIL
    安装指令

    pip install scrapy
    pip install pillow
    

    scrapy在windows下需要成功运行的话,还需要安装pywin32

    三. 需要掌握的知识

    scrapy的基础知识
    xpath或者css的选择器如何使用
    如何使用浏览器查看指定网页元素的标签元素

    四. 爬取逻辑

    1. 通过初始链接,先循环抓取第一页每一位老师的姓名、职称、专业、邮箱、图片链接、详情页信息。
    2. 详情页信息是在循环中,抓取到一位老师的详情页链接后,将链接插入爬取队列,爬取完详情页老师的剩余信息后,保存这位老师的所有信息,然后再抓取下一位老师的信息。
    3. 然后抓取下一页按钮的链接,若有,重复以上循环;没有,则结束。


      爬取流程

    五. 项目目录

    scrapy_learn/
        scrapy.cfg
        scrapy_learn/
            __init__.py
            filterTags.py  #网上找到的去除HTML标签的方法
            items.py  #定义爬取内容
            pipelines.py  #图片下载器
            settings.py    #项目设置文件
            spiders/
                __init__.py
                tutorSpider.py    #爬虫文件(编写爬虫规则)
    

    六. 关键代码

    1. items.py
      定义要爬取的内容
    
    # -*- coding: utf-8 -*-
    
    # Define here the models for your scraped items
    #
    # See documentation in:
    # https://doc.scrapy.org/en/latest/topics/items.html
    
    import scrapy
    
    
    class TutorItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        name = scrapy.Field() #姓名
        position = scrapy.Field() #职称
        major = scrapy.Field() #专业
        email = scrapy.Field() #邮箱
        description = scrapy.Field()  #简介
        researchResult = scrapy.Field() #代表性研究成果
        award = scrapy.Field() #获奖情况
        sciResearPro = scrapy.Field() #科研项目
        talentTrain = scrapy.Field() #人才培养
        image_urls = scrapy.Field() #图片链接
        image = scrapy.Field() #图片
        image_paths = scrapy.Field()
    
    1. TutorSpider.py
      编写爬虫规则
    # -*- coding:UTF-8 -*-
    import scrapy
    from scrapy_learn.items import TutorItem
    from scrapy_learn.filterTags import filter_tags
    
    
    
    class TutorSpider(scrapy.Spider):
        name = 'tutor'
        allowed_domains = ['ggglxy.scu.edu.cn']
        start_urls=['http://ggglxy.scu.edu.cn/index.php?c=article&a=type&tid=18']
        # 初始化item对象保存爬取的信息
        item = TutorItem()
        
        def parse(self,response):
            for tutor in response.xpath("//li[@class='fl']"):
                # 爬取姓名,职称,专业,邮箱
                item = TutorItem()
                item['image_urls'] = {"http://ggglxy.scu.edu.cn"+tutor.xpath("div[@class='l fl']/a/img/@src").extract_first()}
                item['name'] = tutor.xpath("div[@class='r fr']/h3[@class='mb10']/text()").extract_first()
                item['position'] = tutor.xpath("div[@class='r fr']/p[@class='color_main f14']/text()").extract_first()
                item['major'] = tutor.xpath("div[@class='r fr']/div[@class='desc']/p[1]/text()").extract_first()
                item['email'] = tutor.xpath("div[@class='r fr']/div[@class='desc']/p[2]/text()").extract_first()
                 
                # 获取详情页的地址并传送给单个页面处理函数进行处理 -> parse_details()
                href = tutor.xpath("div[@class='l fl']/a/@href").extract_first()
                url = response.urljoin(href)
                request = scrapy.Request(url,callback=self.parse_details)
                request.meta['item'] = item
                yield request
    
            ## 是否还有下一页,如果有的话,则继续
            next_page=response.xpath("//div[@class='pager cf tc pt10 pb10 mobile_dn']/li[last()-1]/a/@href").extract_first()
            if next_page is not None:
                next_pages = response.urljoin(next_page)
                ## 将 「下一页」的链接传递给自身,并重新分析
                yield scrapy.Request(next_pages, callback = self.parse)
    
        # 编写详情页爬取方法
        def parse_details(self, response):
            item = response.meta['item']
            item['description'] = response.xpath("//div[@class='r fr']/div/text()").extract_first()
            item['researchResult'] = filter_tags(response.xpath("//div[@class='right_info p20']/div[2]").extract_first())
            item['award'] = filter_tags(response.xpath("//div[@class='right_info p20']/div[3]").extract_first())
            item['sciResearPro'] = filter_tags(response.xpath("//div[@class='right_info p20']/div[4]").extract_first())
            item['talentTrain'] = filter_tags(response.xpath("//div[@class='right_info p20']/div[5]").extract_first())
            yield item
    
    1. pipelines.py
      下载图片
    # -*- coding: utf-8 -*-
    
    # Define your item pipelines here
    #
    # Don't forget to add your pipeline to the ITEM_PIPELINES setting
    # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
    
    
    
    import scrapy
    from scrapy.pipelines.images import ImagesPipeline
    from scrapy.exceptions import DropItem
    
    class ScrapyLearnPipeline(object):
        def process_item(self, item, spider):
            return item
     
    class TutorImagesPipeline(ImagesPipeline):
        def get_media_requests(self, item, info):
            for image_url in item['image_urls']:
                yield scrapy.Request(image_url)
     
        def item_completed(self,results,item,info):
            image_paths = [x['path'] for ok,x in results if ok]
    #         if not image_paths:
    #             raise DropItem("Item contains no images")
            item['image_paths'] = image_paths
            return item
    
    1. filterTags.py
      去除HTML标签
    # -*- coding: utf-8-*-  
    import re  
    ##过滤HTML中的标签  
    #将HTML中标签等信息去掉  
    #@param htmlstr HTML字符串.  
    def filter_tags(htmlstr):  
        #先过滤CDATA  
        re_cdata=re.compile('//<!CDATA\[[>]∗//CDATA\[[>]∗//\]>',re.I) #匹配CDATA  
        re_script=re.compile('<\s*script[^>]*>[^<]*<\s*/\s*script\s*>',re.I)#Script  
        re_style=re.compile('<\s*style[^>]*>[^<]*<\s*/\s*style\s*>',re.I)#style  
        re_br=re.compile('<br\s*?/?>')#处理换行  
        re_h=re.compile('</?\w+[^>]*>')#HTML标签  
        re_comment=re.compile('<!--[^>]*-->')#HTML注释  
        s=re_cdata.sub('',htmlstr)#去掉CDATA  
        s=re_script.sub('',s) #去掉SCRIPT  
        s=re_style.sub('',s)#去掉style  
        s=re_br.sub('\n',s)#将br转换为换行  
        s=re_h.sub('',s) #去掉HTML 标签  
        s=re_comment.sub('',s)#去掉HTML注释  
        #去掉多余的空行  
        blank_line=re.compile('\n+')  
        s=blank_line.sub('\n',s)  
        s=replaceCharEntity(s)#替换实体  
        return s  
      
    ##替换常用HTML字符实体.  
    #使用正常的字符替换HTML中特殊的字符实体.  
    #你可以添加新的实体字符到CHAR_ENTITIES中,处理更多HTML字符实体.  
    #@param htmlstr HTML字符串.  
    def replaceCharEntity(htmlstr):  
        CHAR_ENTITIES={'nbsp':' ','160':' ',  
                    'lt':'<','60':'<',  
                    'gt':'>','62':'>',  
                    'amp':'&','38':'&',  
                    'quot':'"''"','34':'"',}  
          
        re_charEntity=re.compile(r'&#?(?P<name>\w+);')  
        sz=re_charEntity.search(htmlstr)  
        while sz:  
            entity=sz.group()#entity全称,如>  
            key=sz.group('name')#去除&;后entity,如>为gt  
            try:  
                htmlstr=re_charEntity.sub(CHAR_ENTITIES[key],htmlstr,1)  
                sz=re_charEntity.search(htmlstr)  
            except KeyError:  
                #以空串代替  
                htmlstr=re_charEntity.sub('',htmlstr,1)  
                sz=re_charEntity.search(htmlstr)  
        return htmlstr  
      
    def repalce(s,re_exp,repl_string):  
        return re_exp.sub(repl_string,s)  
    

    七. 项目设置

    要输出中文到文件中,需要在settings.py中加入

    FEED_EXPORT_ENCODING = 'utf-8'
    

    要爬取图片到本地,需要在settings.py中加入

    ITEM_PIPELINES = {
        'scrapy_learn.pipelines.TutorImagesPipeline': 1,
    }
    IMAGES_STORE = 'D:\MyWorkspace\PythonWorkspace\scrapy_learn\img' #图片存储目录
    # 30天的图片失效期限
    IMAGES_EXPIRES = 30
    

    八. 遇到的问题

    1. 爬取图片的时候,没有办法爬取其他设置的item
      解决:
      爬取图片,写items.py文件的时候,一定要写这三行
    image_urls = scrapy.Field() #图片链接
    image = scrapy.Field() #图片
    image_paths = scrapy.Field() #图片路径
    
    1. 爬取图片时,只能爬取带图片的老师的信息
      解决:
      将TutorImagePipeline类中 item_completed函数中这两行注释掉:
    #         if not image_paths:
    #             raise DropItem("Item contains no images")
    

    这两行的意思是,这一整个item如果没有图片的话,则丢掉整个item。所以才会导致没有图片的老师信息爬取不到。

    1. 环境问题
      安装和运行scrapy的过程中会遇到很多环境上的问题,这是因为相应的依赖没有安装好。这个时候就需要查看错误信息,然后利用百度、谷歌去搜索相应的依赖应该如何安装。

    九. 运行爬虫及爬取结果

    当代码编写无误后,在命令行界面中,进入项目文件夹,即scrapy_learn目录下,运行以下代码即可开始爬虫。

    scrapy crawl tutor -o tutor.json
    

    以上代码是运行爬虫,并将爬取的内容保存为json格式的文件。
    爬取结果:


    tutor.json

    爬取照片:


    爬取教师照片

    相关文章

      网友评论

          本文标题:使用scrapy爬取四川大学公共管理学院教师信息实验报告

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