scrapy 爬取Curlie实验报告

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

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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容