美文网首页
scrapy 爬取Curlie实验报告

scrapy 爬取Curlie实验报告

作者: 何春春春春 | 来源:发表于2018-05-20 20:30 被阅读0次

(代码文件链接见第六点)

1.实验目的

本次实验是为了掌握scrapy爬取层级网站信息的技巧。

2.实验要求

使用scrapy爬取Curlie网站的News目录下(https://curlie.org/News/)所有的子项目的网站标题、Url和网站描述信息,并且将News目录下面的子项目生成具有Json格式的目录结构的目录。

3.实验工具

centos2.7、Python3.6.5、scrapy1.5.0

4.实验方案设计

分析目标网页规则,制定爬虫策略--->编写Python代码--->进行代码调试---->处理爬虫数据,生成最后爬虫结果

5.实验过程

  • 分析目标网页规则,制定爬虫策略


    Subcategories

    1.NEWS下面的Subcategories内容。如图


    Subcategories .
    可以看出我们需要爬取的信息都在//section[@class="children"]//div[@class="cat-item"]/div标签中。

    针对每一个Subcategories我们需要爬取的信息有

  • 网站名称 name
  • 网站url url

2.根据实验要求可以看出我们主要爬取的是NEWS下面的Subcategories 下的Sites的内容,由图可以看出,我们需要爬取的列表信息都在//section[@class='children']/div这个标签下。
针对每一个Sites我们需要爬取的信息有


对象

这三个对象在网站中的位置为


position
因而我们小组的大致爬虫思路为:因为需要遍历News下的所有目录,所以我们小组选择使用适用于爬取批量网页的类CrawlSpider,用rules来提取页面的链接。linkextractor(allow=(正则表达式),restrict_xpaths=())提取页面内的超链接,allow限制只允许提取符合正则表达式的url,restrict_xpaths用xpath定位提取的url在页面的位置,和allow共同作用过滤链接。Rule从起始页用提取符合规则的链接,通过这个链接再生成Request,如此循环,直至没有符合要求的链接。并用callback解析返回的结果。
下面是我们的python代码思路解析
代码思路
  • 编写Python代码
    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 CurlieItem(scrapy.Item):
          # define the fields for your item here like:
          # name = scrapy.Field()
          category = scrapy.Field()       # 当前所属目录
          subcategory = scrapy.Field()    # 子目录
          name = scrapy.Field()           #子目录项目名字
          url = scrapy.Field()            #子目录项目url
          sites = scrapy.Field()          #当前网页下的网站
          title = scrapy.Field()          # 网站标题
          site_url = scrapy.Field()       #网站url
          description = scrapy.Field()    #网站概述
    

    spider爬虫代码(curlie.py)

      import scrapy
      from urllib import parse
      from scrapy.spiders import CrawlSpider, Rule
      from scrapy.linkextractors import LinkExtractor
      from curlie.items import CurlieItem
    
      class CurlieSpider(CrawlSpider):
          name = "curlie"
          allowed_domains = ["curlie.org"]
          start_urls = ["https://curlie.org/News/"
          rules =(
       Rule(LinkExtractor(allow=(r'https://curlie.org/News/[\s\S]*'),restrict_xpaths = ('//section[@class="children"]//div[@class="cat-item"]')), callback="parse_item" ,follow=True),#只爬News路径下的
      #Rule(LinkExtractor(restrict_xpaths=('//section[@class="children"]//div[@class="cat-item"]')),callback="parse_item", follow=True), #News子分类下的都爬)
    
          def parse_item(self,response):
              item = CurlieItem()
              #当前所属目录分类
              item['category'] = response.url.lstrip('https://curlie.org')
    
              #当前目录子目录
              item['subcategory'] = []
              for sub in response.xpath('//section[@class="children"]//div[@class="cat-item"]'):
                  subcategory = {}
                  subcategory['name'] = sub.xpath('.//a/div/text()').extract()[1].strip()
                  subcategory['url'] = parse.urljoin(response.url, sub.xpath('.//a/@href').extract_first())
                  item['subcategory'].append(subcategory)
    
              #当前目录下的网站
              item['sites'] = []
              for site in response.xpath('//section[@class="results sites"]//div[@class="site-item "]'):
                  sites = {}
                  sites['title'] = site.xpath('./div[@class="title-and-desc"]/a/div/text()').extract_first()
                  sites['site_url'] = parse.urljoin(response.url, site.xpath('./div[@class="title-and-desc"]/a/@href').extract_first())
                  sites['description'] = site.xpath('.//div[@class="site-descr "]/text()').extract_first().strip()
                  item['sites'].append(sites)
              yield item
    
  • 爬取数据过程中遇到的问题
    1.Curlie网站的反爬虫机制


    Curlie网站为了防止爬虫抓取页面频率过快造成服务器瘫痪,设置了一个较低的抓取请求频率。即crawler程序两次进入站点时,以1秒为单位的最低延时。我们小组爬虫的时候,爬取100多条的数据的时候即被封了号,不能再爬取任何信息。需要过了几个小时才能重新抓取网页信息。
    2.解析网页结构的时候发现,NEWS下面的部分网页内容是其他或者链接到其他目录的内容,例如News/By Subject/Accounting文件夹下面的url为https://curlie.org/Business/Accounting/News_and_Media,我们需要进行网页内容的筛选。
    3.起始页面的sites没有爬取成功。我们小组分析是因为起始页面的通过parse函数解析,之后的页面才由rule规则指定的函数解析。因而起始页的sites没有爬取成功。
  • 解决办法
    1.反爬虫的解决办法
    查询得知,当我们需要大量的爬取网站信息时,除了切换User-Agent之外,另外一个重要的方式就是设置IP代理,以防止我们的爬虫被拒绝。我们小组商量决定采取设置云服务器的IP代理。具体过程参考了http://www.cnblogs.com/cnkai/p/7401526.html 教程
    2.采用rules来提取链接。利用allow中的正则表达式将位于news目录下面的url提取出来,同时结合restrict_xpaths,使用xpath表达式,和allow共同作用过滤链接。
    3.针对起始页面的sites没有爬取成功,我们小组提出了两种解决思路。首先,将start_url修改为http://curlie.org/,修改Rule,让NEWS页面也能让回调函数解析,然后重新爬取数据。第二种是单独截取起始页的内容。考虑到爬取的页面较多,时间较长,因而我们小组选择第二种方法。
    第二次截取页面内容的spider代码(curlie1.py)为:

      import scrapy
      from urllib import parse
      from scrapy.spiders import CrawlSpider, Rule
      from scrapy.linkextractors import LinkExtractor
      from curlie.items import CurlieItem
    
      class CurlieSpider(CrawlSpider):
          name = "curlie1"
          allowed_domains = ["curlie.org"]
          start_urls = ["https://curlie.org/News/"]
    
          def parse(self,response):
              item = CurlieItem()
              #当前所属目录分类
              item['category'] = response.url.lstrip('https://curlie.org')
    
              #当前目录下的网站
              item['sites'] = []
              for site in response.xpath('//section[@class="results sites"]//div[@class="site-item "]'):
                  sites = {}
                  sites['title'] = site.xpath('./div[@class="title-and-desc"]/a/div/text()').extract_first()
                  sites['site_url'] = parse.urljoin(response.url, site.xpath('./div[@class="title-and-desc"]/a/@href').extract_first())
                  sites['description'] = site.xpath('.//div[@class="site-descr "]/text()').extract_first().strip()
                  item['sites'].append(sites)
              yield item
    

6.实验结果

附代码及结果数据文件:curlie项目代码及结果数据文件(news.jl、curlie1.json)

部分结果截图
News页面下的部分站点.png

7.其它尝试

除了上述的数据之外,我们通过变更Rule爬取了url中包含'News'的站点:
(变更后的Rule)——

  Rule(LinkExtractor(allow=(r'[\s\S]*News[\s\S]*'),restrict_xpaths=('//section[@class="children"]//div[@class="cat-item"]')),callback="parse_item",follow=True),#url包含News的都要

详细结果文件见代码文件链接中的results.jl
下面是部分结果截图


部分结果.png

相关文章

网友评论

      本文标题:scrapy 爬取Curlie实验报告

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