深入使用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]
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
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
数据存入应用
作者觉得保存到数据库的模块太复杂繁重,不想影响爬虫框架的核心开发所以剔除了。
一般数据导入有一下2种方式:
- 通过rake task把json、csv等本地数据导入到Rails应用
- 通过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
这样定时任务就完成了
爬虫状态监控
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
生产环境部署
框架内置了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
最终whenever成功执行,那爬虫就成功部署完了。