布尔方法在不同情况下不返回 [RUBY]
Boolean method not returning in different situations [RUBY]
我正在构建一个简单的网络抓取工具(从 indeed.com 抓取工作)用于练习,我正在尝试实现以下方法 (low_salary?(salary))。该方法的目的是比较最低(即期望)薪水,将其与工作对象(@salary)中包含的提供薪水进行比较:
class Job
attr_reader :title, :company, :location, :salary, :url
def initialize(title, company, location, salary, url)
@title = title
@company = company
@location = location
@salary = salary
@url = url
end
def low_salary?(minimum_salary)
return if !@salary
minimum_salary < @salary.split(/[^\d]/)[1..2].join.to_i
end
end
当comapring @salary 和给它的min_salary 变量时,该方法工作正常,delete_if 适当地删除return 对low_salary 正确的元素?并且 returns 在@salary 为 nil 时正确(实际上列表并不总是包括薪水,所以我的假设是会有一些 nil 值)在以下测试程序中(另外:我不确定为什么 minimum_salary < @salary 有效,但 @salary < minimum_salary 无效,但这正是我想要的):
require_relative('job_class.rb')
job = Job.new("designer", "company", "location", "£23,000 a year", "url")
job_results = []
job_results.push(job)
min_salary = 50000
print job.low_salary?(min_salary)
job_results.delete_if { |job| job.low_salary?(min_salary) }
print job_results
但是在我的抓取程序中,调用方法时出现无方法错误:job_class.rb:16:in "low_salary?": undefined method `join' for nil:NilClass (NoMethodError)
require 'nokogiri'
require 'open-uri'
require_relative 'job_class.rb'
class JobSearchTool
def initialize(job_title, location, salary)
@document = Nokogiri::HTML(open("https://uk.indeed.com/jobs?q=#{job_title.gsub('-', '+')}&l=#{location}"))
@job_listings = @document.css('div.mosaic-provider-jobcards > a')
@salary = salary.to_i
@job_results = []
end
def scrape_jobs
@job_listings.each do |job_card|
@job_results.push(Job.new(
job_card.css('h2 > span').text, #title
job_card.css('span.companyName').text, #company
job_card.css('div.companyLocation').text, #location
job_card.css('span.salary-snippet').text, #salary
job_card['href']) #url
)
end
end
def format_jobs
@job_results.each do |job|
puts <<~JOB
#{job.title} - #{job.company} in #{job.location} :#{job.salary}
Apply at: #{job.url}
---------------------------------------------------------------------------------
JOB
end
end
def check_salary
@job_results.delete_if { |job| job.low_salary?(@salary) }
end
def run
scrape_jobs
check_salary
format_jobs
end
if __FILE__ == [=13=]
job_search_tool = JobSearchTool.new(ARGV[0], ARGV[1], ARGV[2])
job_search_tool.run
end
显然,抓取程序中的某些内容以某种方式影响了该方法,但我不明白它可能是什么。我以与测试程序完全相同的方式使用该方法,那么当@salary 为 nil 时导致该方法不 return 的区别是什么?
快速搜索您正在抓取的 URL 显示有没有薪水的职位发布,因此,当您从该 HTML 元素获取数据并初始化一个新的 Job 对象,薪水是一个空字符串,并且知道 "".split(/[^\d]/)[1..2]
returns nil,这就是你得到的错误。
您必须添加一种方法来处理没有薪水的招聘职位:
class Job
attr_reader :title, :company, :location, :salary, :url
def initialize(title, company, location, salary, url)
@title = title
@company = company
@location = location
@salary = salary.to_s # Explicit conversion of nil to string
@url = url
end
def low_salary?(minimum_salary)
return if parsed_salary.zero? # parsed_salary returns always an integer,
# so you can check when is zero,
# and not just when is falsy
minimum_salary < parsed_salary
end
private
def parsed_salary
salary[/(?<=£)(\d|,)*(?=\s)/]
.to_s # converts nil to "" if the regex doesn't capture anything
.tr(",", "") # removes the commas to parse the string as an integer
.to_i # parses the string to its corresponding integer representation
end
end
请注意,正则表达式并不意味着捕获所有内容,但它适用于网站中呈现的薪水。
我正在构建一个简单的网络抓取工具(从 indeed.com 抓取工作)用于练习,我正在尝试实现以下方法 (low_salary?(salary))。该方法的目的是比较最低(即期望)薪水,将其与工作对象(@salary)中包含的提供薪水进行比较:
class Job
attr_reader :title, :company, :location, :salary, :url
def initialize(title, company, location, salary, url)
@title = title
@company = company
@location = location
@salary = salary
@url = url
end
def low_salary?(minimum_salary)
return if !@salary
minimum_salary < @salary.split(/[^\d]/)[1..2].join.to_i
end
end
当comapring @salary 和给它的min_salary 变量时,该方法工作正常,delete_if 适当地删除return 对low_salary 正确的元素?并且 returns 在@salary 为 nil 时正确(实际上列表并不总是包括薪水,所以我的假设是会有一些 nil 值)在以下测试程序中(另外:我不确定为什么 minimum_salary < @salary 有效,但 @salary < minimum_salary 无效,但这正是我想要的):
require_relative('job_class.rb')
job = Job.new("designer", "company", "location", "£23,000 a year", "url")
job_results = []
job_results.push(job)
min_salary = 50000
print job.low_salary?(min_salary)
job_results.delete_if { |job| job.low_salary?(min_salary) }
print job_results
但是在我的抓取程序中,调用方法时出现无方法错误:job_class.rb:16:in "low_salary?": undefined method `join' for nil:NilClass (NoMethodError)
require 'nokogiri'
require 'open-uri'
require_relative 'job_class.rb'
class JobSearchTool
def initialize(job_title, location, salary)
@document = Nokogiri::HTML(open("https://uk.indeed.com/jobs?q=#{job_title.gsub('-', '+')}&l=#{location}"))
@job_listings = @document.css('div.mosaic-provider-jobcards > a')
@salary = salary.to_i
@job_results = []
end
def scrape_jobs
@job_listings.each do |job_card|
@job_results.push(Job.new(
job_card.css('h2 > span').text, #title
job_card.css('span.companyName').text, #company
job_card.css('div.companyLocation').text, #location
job_card.css('span.salary-snippet').text, #salary
job_card['href']) #url
)
end
end
def format_jobs
@job_results.each do |job|
puts <<~JOB
#{job.title} - #{job.company} in #{job.location} :#{job.salary}
Apply at: #{job.url}
---------------------------------------------------------------------------------
JOB
end
end
def check_salary
@job_results.delete_if { |job| job.low_salary?(@salary) }
end
def run
scrape_jobs
check_salary
format_jobs
end
if __FILE__ == [=13=]
job_search_tool = JobSearchTool.new(ARGV[0], ARGV[1], ARGV[2])
job_search_tool.run
end
显然,抓取程序中的某些内容以某种方式影响了该方法,但我不明白它可能是什么。我以与测试程序完全相同的方式使用该方法,那么当@salary 为 nil 时导致该方法不 return 的区别是什么?
快速搜索您正在抓取的 URL 显示有没有薪水的职位发布,因此,当您从该 HTML 元素获取数据并初始化一个新的 Job 对象,薪水是一个空字符串,并且知道 "".split(/[^\d]/)[1..2]
returns nil,这就是你得到的错误。
您必须添加一种方法来处理没有薪水的招聘职位:
class Job
attr_reader :title, :company, :location, :salary, :url
def initialize(title, company, location, salary, url)
@title = title
@company = company
@location = location
@salary = salary.to_s # Explicit conversion of nil to string
@url = url
end
def low_salary?(minimum_salary)
return if parsed_salary.zero? # parsed_salary returns always an integer,
# so you can check when is zero,
# and not just when is falsy
minimum_salary < parsed_salary
end
private
def parsed_salary
salary[/(?<=£)(\d|,)*(?=\s)/]
.to_s # converts nil to "" if the regex doesn't capture anything
.tr(",", "") # removes the commas to parse the string as an integer
.to_i # parses the string to its corresponding integer representation
end
end
请注意,正则表达式并不意味着捕获所有内容,但它适用于网站中呈现的薪水。