深入使用kimuraframework的项目模式抓取网页信息,存入应用的数据库,发布上线并定时执行

之前的文章《Ruby爬虫框架kimuraframework实践(入门)》中已经实践了抓取字幕组影视库保存为json的测试爬虫。但只是仅仅实现而已,这次我们深入的来了解下kimuraframework的更多功能,把爬虫工具与实际应用结合起来。


还有哪些工作?



优化数据处理


kimuraframework默认引入了Active Support,所以可以用很多现成方法来改进之前很原始的处理方式。

text = "                        【美剧】《相对宇宙》"
# old
text.gsub("【美剧】", "").strip
# new
text.remove("【美剧】").squish
#=> "《相对宇宙》"
#strip只去头尾空格
#squish除了去头尾空格外,还会连续空格转为1个空格
#https://api.rubyonrails.org/classes/String.html#method-i-squish
text1 = "地区:美国"
text2 = "类型:剧情/科幻"

#字符截取还有多种选择,按不用需求挑选
text1.remove("地区:")
text2.remove("类型:")
text1.from(3).to(-1)
text2.from(3).to(-1)
#=> "美国"
#=> "剧情/科幻"

针对中文数据能处理的内容比较少,如果获取的是英文内容可参考Active Support接口文档


过滤无效数据


针对数据的过滤kimuraframework提供了pipelines

#spiders/application_spider.rb
# To process item through pipelines pass item to the `send_item` method
@pipelines = [:validator, :saver]

WX20190212-160029


Validator

试着设置一些过滤规则:”地区必须是美国、排名在1000以内、标题不可重复“。(这里的判断条件是剔除数据用的,注意不要写反了)

class Validator < Kimurai::Pipeline
  def process_item(item, options: {})
  
    unless unique?(:title, item[:title])
      raise DropItemError, "标题不能重复"
    end
  
    if item[:region] != "美国"
      raise DropItemError, "地区不是美国"
    end

    if item[:rank] > 1000
      raise DropItemError, "排名大于1000"
    end

    # Pass item to the next pipeline (if it wasn't dropped)
    item
  end
end

只要把之前的保存方法改为send_item,获取的数据就会自动按照流程去依次执行,只要有一个条件不符合就跳过至下一个。(unique判断只在一次爬虫命令的执行过程中有效,并不是读取json文件来判断的)

# zimuzu.rb
# ...
    #save_to "zimuzu.json", item, format: :pretty_json
    send_item item

有2种方式执行爬虫

bundle exec kimurai crawl zimuzu_advance
#runner可以并行多个爬虫文件,并可在dashboard中查看状态
bundle exec kimurai runner --include zimuzu_advance

WX20190212-174838


Saver

存储流程中可以配置数据的去向,可以保存为json、发送到API接口或者通过数据库client直接存到各类数据库。

class Saver < Kimurai::Pipeline
  def process_item(item, options: {})
    # Here you can save item to the database, send it to a remote API or
    # simply save item to a file format using `save_to` helper:

    # To get the name of a current spider: `spider.class.name`
    # save_to "db/#{spider.class.name}.json", item, format: :pretty_json

    item
  end
end


数据存入应用


WX20190213-204903

作者觉得保存到数据库的模块太复杂繁重,不想影响爬虫框架的核心开发所以剔除了。

一般数据导入有一下2种方式:

  1. 通过rake task把json、csv等本地数据导入到Rails应用
  2. 通过api接口直接在爬虫数据发送到Rails应用


执行定时任务


框架中已经配置好了whenever schedule.rb,只需要选择想要执行的爬虫文件就行了。

#config/schedule.rb
require 'tzinfo'

env :PATH, ENV["PATH"]

set :chronic_options, hours24: true
set :ruby_path, "~/.rbenv/versions/2.6.0/bin/"

def local_to_utc(time_string, zone:)
  TZInfo::Timezone.get(zone).local_to_utc(Time.parse(time_string))
end

job_type :crawl,  "cd :path && KIMURAI_ENV=:environment #{ruby_path}bundle exec kimurai crawl :task :output"
job_type :runner, "cd :path && KIMURAI_ENV=:environment #{ruby_path}bundle exec kimurai runner --include :include --jobs :task :output"

every 1.minute do
  crawl "zimuzu_advance", output: "log/test_schedule.log"
  runner 2, include: "zimuzu_advance", output:"log/runner.log"
end

WX20190212-190725

这样定时任务就完成了

WX20190212-190819

WX20190213-101328


爬虫状态监控


v1.0.0开始dashboard被移除,单独成为了一个gem:kimurai-dashboard

gem 'kimurai-dashboard', require: false
gem 'sqlite3'
# config/boot.rb
# ...

Kimurai.configuration.stats_database_url = "sqlite://db/spiders_runs_#{Kimurai.env}.sqlite3"
require 'kimurai/dashboard'
# config/application.rb

Kimurai.configure do |config|
  # ...

  config.dashboard = {
    bind_address: "0.0.0.0",
    port: 3001,
    basic_auth: { username: "admin", password: "123456" }
  }
end
# 启动
bundle exec kimurai dashboard

WX20190213-104047 WX20190213-104102 WX20190213-104114


生产环境部署


框架内置了deploy命令,通过ansible的playbook实现的,安装完ansible直接用就行了,环境配置setup和部署deploy都有。

# 部署机爬虫环境安装
kimurai setup pi@192.168.31.9 --ask-auth-pass
# 部署到树莓派上,我用的是sshpass方式验证,直接配置免密也可以
kimurai deploy pi@192.168.31.9 --ask-auth-pass --repo-url git@git.xxxxxx.com:xxx/web_spiders_demo.git

WX20190213-200610

最终whenever成功执行,那爬虫就成功部署完了。