2021-08-17
Ruby是非常优雅高效的编程语言,这次我们用Ruby演示如何编写爬虫程序抓取拉钩的职位信息。
本文会以抓取拉钩职位信息为目标,展示Ruby生态中的编写爬虫可能会用到的工具和相关技术。我们会利用Ruby语言的HTTP请求库和HTML格式解析库来抓取静态网页。然后继续探索如何抓取动态网页的内容。
请注意:在Ruby生态中,有很多优秀的工具来帮助实现爬虫程序,我们无法一一覆盖,大家可以自行探索。
我们假定你对Ruby的基本语法有所了解,安装好了ruby开发环境。如果没有,请参考一下链接:
编写爬虫的第一步一般就是要发起请求到目标网页,把网页内容请求回来,然后对请求返回内容进行处理。Ruby中内置了HTTP请求标准库,同时也有很多优秀的第三方库帮助处理HTTP请求。我们主要列举了最通用的三种发送HTTP请求的方式:
Net/HTTP
Faraday
HTTParty
用户可根据实际情况和使用习惯选取其中一个方式即可。
我们先准备好我们的项目代码目录:
mkdir scraping-lagou
cd scraping-lagou
touch lagou.rb
Net/HTTP
Ruby语言的标准库中自带了HTTP请求的支持,即:Net/HTTP
。使用Net/HTTP
发送请求的代码如下:
require 'open-uri'
require 'Net/HTTP'
url = "https://www.lagou.com/guangzhou/"
uri = URI.parse(url)
response = Net::HTTP.get_response(uri)
puts response.body
代码很直接,先用open-uri
标准库处理需要访问的链接地址,然后使用Net/HTTP
发送HTTP请求并获取响应。响应的内容保存在response.body
中。
Faraday
Faraday
是最受欢迎的HTTP请求库,功能强大使用方便。因为Faraday
是第三方Gem,我们先创建我们的Gemfile:touch Gemfile
管理我们的依赖。然后编辑Gemfile添加需要安装的库:
source 'https://rubygems.org'
gem 'faraday'
然后运行:bundle install
。
编写代码:
require 'faraday'
response = Faraday.get('https://www.lagou.com/guangzhou/')
puts response.body
HTTParty
HTTParty
也是非常优秀的HTTP请求库,同样的我们添加到依赖的Gemfile中,同时使用bundler来安装依赖。
然后看看怎么使用HTTParty
发送请求:
require 'HTTParty'
response = HTTParty.get('https://www.lagou.com/guangzhou/')
puts response.body
几乎跟Faraday
一样。无论你用那种方式发送请求,这时候我们应该已经能拿到请求响应回来的HTML内容了。下一步我们要解析HTML。
Nokogiri
解析HTML一旦我们拿到了目标网页的HTML内容,我们就需要解析HTML内容,然后抽取我们需要的数据内容了。要解析HTML,我们需要依赖Nokogiri
库。
第一步还是在Gemfile中添加我们需要的依赖:
source 'https://rubygems.org'
gem 'faraday'
gem 'httparty'
gem 'nokogiri'
然后 bundle install
安装依赖。
上面的三种请求方式,我们需要解析的HTML内容都已经保存在response.body
里面了,现在添加代码解析HTML:
require 'faraday'
require 'nokogiri'
response = Faraday.get('https://www.lagou.com/guangzhou/')
doc = Nokogiri::HTML(response.body)
doc
参数就是经过Nokogiri
解析过的对象,事实上类似浏览器解析HTML内容形成的一系列树状结构的节点内容。Nokogiri
优秀的地方在于解析好的HTML节点对象支持CSS和XPath选择器方法,能十分方便的定位我们需要的节点并抽取对应的内容。
我们先分析网页结构:
对应的我们可以开始抽取,代码如下:
doc = Nokogiri::HTML(response.body)
jobs = []
doc.css('ul.position_list_ul li.position_list_item').each do |li|
j = {}
j['title'] = li.at_css('a.position_link').content
j['salary'] = li.at_css('span.salary').content
j['company'] = li.at_css('h3.company_name a').content
jobs.append(j)
end
puts jobs
我们首先从解析的节点树找到职位的列表元素。然后在列表元素中找到对应的内容,我们现在只抽取职位名,薪资范围和公司名这三个主要的信息。这里请注意css
方法默认会返回数组,如果明确知道是单个元素(例如在列表元素内,只有一个职位名)的话,直接用at_css
方法会更加方便。
运行爬虫程序,应该就能看到我们抓取的职位信息了:
➜ scraping-lagou ruby lagou.rb
{"title"=>"社群文案策划", "salary"=>"6k-9k·13薪", "company"=>"千聊"}
{"title"=>"测试工程师(电商) (MJ004308)", "salary"=>"10k-20k·13薪", "company"=>"欢聚集团(JOYY Inc.)"}
{"title"=>"高级客户执行", "salary"=>"9k-15k·13薪", "company"=>"驰骛科技ChiefClouds"}
{"title"=>"销售顾问", "salary"=>"10k-15k·13薪", "company"=>"知衣科技"}
...
爬虫脚本的基本功能已经完成了,不过我们现在的数据只是打印到标准输出上,不方便后续使用。我们利用标准库中的csv
模块来帮助我们保存成文件。
require 'faraday'
require 'nokogiri'
require 'csv'
response = Faraday.get('https://www.lagou.com/guangzhou/')
doc = Nokogiri::HTML(response.body)
jobs = []
doc.css('ul.position_list_ul li.position_list_item').each do |li|
j = {}
j['title'] = li.at_css('a.position_link').content
j['salary'] = li.at_css('span.salary').content
j['company'] = li.at_css('h3.company_name a').content
jobs.append(j)
end
CSV.open('lagou_jobs.csv', "w") do |csv|
csv << jobs.first.keys
jobs.each do |j|
csv << j.values
end
end
Bingo!我们抓取了拉钩首页的最新职位的相关信息并保存成了csv格式的文件以备后用。
上面的爬虫只能抓取静态网页内容,如果我们要抓取动态网页的内容我们应该怎么办呢。有两种选择:
比如我们可以利用ferrum库来帮助驱动headless浏览器。具体可以参看对应的示例代码
另外一种选择,更加方便,让成熟的服务帮助JS渲染,直接获取到渲染以后的HTML内容。五号代理就是其中一个选择。我们只需要修改一行代码就能完成动态网页的抓取,其他代码都不需要改变。
require 'faraday'
require 'nokogiri'
require 'csv'
# 直接使用五号代理的API进行JS渲染
response = Faraday.get('https://api.agentfive.cn/v1', {url: 'https://www.lagou.com/guangzhou/', key: 'YOUR-API-KEY', render: true})
doc = Nokogiri::HTML(response.body)
jobs = []
doc.css('ul.position_list_ul li.position_list_item').each do |li|
j = {}
j['title'] = li.at_css('a.position_link').content
j['salary'] = li.at_css('span.salary').content
j['company'] = li.at_css('h3.company_name a').content
jobs.append(j)
end
CSV.open('lagou_jobs.csv', "w") do |csv|
csv << jobs.first.keys
jobs.each do |j|
csv << j.values
end
end
Ruby语言动态灵活,生态成熟完善,也是编写爬虫的好选择,希望本文能够展示给大家一些跟爬虫相关的常用库和工具。