ruby - 我检查什么条件以引发自定义错误 Net::OpenTimeout 执行过期错误
问题描述
Open-uri 和 nokogiri 抓取我想要的站点的速度很慢,因此出现 Net::OpenTimeout 执行过期错误。我尝试使用救援编写自定义错误,但是我不知道我可以寻找什么条件来引发该自定义错误。
我尝试了很少的 if else 语句,但我真的只是猜到了如何检查我是否会得到那个错误。我硬编码了一个失败的条件,从而挽救了错误。我对红宝石和自定义错误非常陌生。事实上,这是我的第一次。
class Scrape
Base = 'http://www.wine.com'
@@menu = []
@@pages = []
def self.index
index_url = Base + "/list/wine/7155?sortBy=savings&pricemax=90"
#below is where I need to check for the condition to
raise the error
if doc = Nokogiri::HTML(open(index_url))
container = doc.css('.prodList')
wines = container.css('.prodItem')
wines.each do |wine|
@@menu << {
:link => wine.css('.prodItemInfo_link').attribute('href').value,
:name => wine.css('.prodItemInfo_name').text,
:rating => (wine.css('.averageRating_average').text.to_i) > 0 ?
(wine.css('.averageRating_average').text) : 'no rating',
:price => wine.css('.productPrice_price-saleWhole').text.strip
}
end
@@menu.each do |item|
Bottle.new.create(item)
end
else
begin
raise Custom_error
rescue Custom_error => error
puts error.message
end
end
end
def self.scrape_page(wine_obj)
wine_link = wine_obj.link
individual_page = Base + wine_link
docu = Nokogiri::HTML(open(individual_page))
y = docu.css('.viewMoreModule_text')
more = docu.css('.viewMoreModule_text')
@@pages << {
:obj => wine_obj,
:name => docu.css('.pipName').text,
:alcohol_percent => y
x = docu.css('.mobileProdAttrs').css('.prodAlcoholPercent')
y = x.css('.prodAlcoholPercent_percent').text,
:price => docu.css('span.productPrice_price-saleWhole').text,
:origin => docu.css('span.prodItemInfo_originText a').text,
:winemaker_notes => docu.css('.viewMoreModule_text').first.text,
:more => y[2].text,
:rating => docu.css('span.averageRating_average').first.text
}
Page.create_find_by_name( @@pages.last )
end
def self.pages
@@pages
end
end
class Cli
def run
puts 'loading from cyberspace'
Scrape.index
Bottle.make_list
controller
end
def controller
input = ''
response = ''
puts ' '
view
while input != 11
response = gets.chomp.to_i
input = "#{response}11".to_i
if input == 111
menu
elsif input == 11
exit
elsif input > 0 && input < 26
find_by_input(input)
elsif input != 0 && input != 111
error_1
end
end
end
def view
puts "welcome to the wine bar"
puts "================="
puts " W I N E "
puts " B A R "
puts "================="
puts " "
puts "type 1 for list of wine"
puts " "
puts "type 0 to exit "
end
def menu
wines = Bottle.list
second_input = ''
while second_input != 0
puts "<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>"
puts "type the corresponding number to view more wine info"
puts
"__________________________________________________________________"
wines.each do |wine|
puts "#{wine.index}) #{wine.name} #{wine.price}"
end
second_input = gets.chomp.to_i
if second_input > 0 && second_input < 26
find_by_input(second_input)
elsif second_input == 0
exit
second_input = 0
elsif second_input > 25 && second_input != 101
error_1
end
end
puts <<-DOC
the the wine number again
for winemaker notes
DOC
end
def find_by_input(input)
while input != 0
selection = Bottle.find_by_input(input)
puts "NAME: #{selection.name}"
puts "PRICE: $#{selection.price}"
puts "RATING: #{selection.rating}"
puts "________________________________________"
puts " type #{input} again "
puts " for more info "
puts " provided by the winemaker "
# reseting input and extending user control functionality
third_input = ''
third_input = gets.chomp.to_i
if third_input == selection.index
response = Scrape.scrape_page(selection)
view_2(response, third_input)
elsif input == 0
exit
end
end
end
def view_2(response, old_input)
next_input = ''
while next_input != 0
puts "Alcohol Percent: #{response.alcohol_percent}"
puts "Winemaker Notes: #{response.winemaker_notes}"
puts " "
puts "Type #{old_input} again for more!!"
next_input = gets.chomp.to_i
if next_input == old_input
input = 0
next_input = 0
# refacort as it puts out 88 again and should not. Also 0 is not
exiting with correct behavior
# refactor so looking for "#{input}"1 to prevent the recall of
input
more(response)
end
end
end
def more(response)
puts response.more
puts menu
end
def error_1
puts " WHOA coder "
puts "type a better number!"
end
def exit
puts <<-DOC
well that was fun
Thank you for checking out
my first cli program
DOC
end
end ```
```class Page
attr_accessor :alcohol_percent, :price, :name, :origin, :winemaker_notes,
:rating, :more, :obj
@@web_pages = []
def self.create_find_by_name(hash)
if answer = @@web_pages.find{ |obj| obj.name == hash[:name]}
answer
else
self.new.create(hash)
end
end
def create(hash)
hash.each do |key, value|
self.send(("#{key}="), value)
end
save
view_more
end
def view_more
@@web_pages.last
end
def save
@@web_pages << self
end
end
attr_accessor :link, :name, :price, :rating, :index
@@bottles = []
def create(hash)
hash.each do |key, words|
self.send(("#{key}="), words )
end
save
end
def save
@@bottles << self
end
def self.make_list
@@numbered_list = @@bottles.sort{ |x,y| x.price <=>
y.price}.map.with_index(1) do
|w,i| w.index = i
w
end
end
def self.list
@@numbered_list
end
def self.find_by_input(input)
a = @@numbered_list.find{ |wine| wine.index == input}
# puts "#{a.name} $#{a.price} rating: #{a.rating}"
# puts "type #{input} again for winemaker notes"
# more = ''
# while more != 0
# more = gets.chomp.to_i
# (input == more) ? (Scrape.scrape_page(a.link)) : (self.list)
# end
end
end
class Scrape
Base = 'http://www.wine.com'
@@menu = []
@@pages = []
def self.index
index_url = Base + "/list/wine/7155?sortBy=savings&pricemax=90"
if doc = Nokogiri::HTML(open(index_url))
container = doc.css('.prodList')
wines = container.css('.prodItem')
wines.each do |wine|
@@menu << {
:link => wine.css('.prodItemInfo_link').attribute('href').value,
:name => wine.css('.prodItemInfo_name').text,
:rating => (wine.css('.averageRating_average').text.to_i) > 0 ?
(wine.css('.averageRating_average').text) : 'no rating',
:price => wine.css('.productPrice_price-saleWhole').text.strip
}
end
@@menu.each do |item|
Bottle.new.create(item)
end
else
begin
raise Custom_error
rescue Custom_error => error
puts error.message
end
end
end
def self.scrape_page(wine_obj)
wine_link = wine_obj.link
individual_page = Base + wine_link
docu = Nokogiri::HTML(open(individual_page))
y = docu.css('.viewMoreModule_text')
more = docu.css('.viewMoreModule_text')
@@pages << {
:obj => wine_obj,
:name => docu.css('.pipName').text,
alcholo = docu.css('.mobileProdAttrs').css('.prodAlcoholPercent'),
:alcohol_percent => alcholo.css('.prodAlcoholPercent_percent').text,
:price => docu.css('span.productPrice_price-saleWhole').text,
:origin => docu.css('span.prodItemInfo_originText a').text,
:winemaker_notes => docu.css('.viewMoreModule_text').first.text,
:more => y[2].text,
:rating => docu.css('span.averageRating_average').first.text
}
Page.create_find_by_name( @@pages.last )
end
def self.pages
@@pages
end
end
当互联网连接中断/太慢时,会引发自定义错误。
解决方案
当抛出异常时,程序会停止其正常流程。您需要用一个子句包围可能引发异常的代码部分begin..rescue
,并尝试处理它、重新引发它或引发另一个异常。
在您的示例中,这将是:
begin
Nokogiri::HTML(open(url))
rescue Net::OpenTimeoutError => e
# log the error message if needed, raise your CustomError instead
raise CustomError, e.message
end
您可以省略, 并在方法的末尾begin
放置一个子句,ruby 会将其解释为好像整个方法体被包裹在一个块中,如下所示:rescue
begin..rescue
def open_page(url)
return Nokogiri::HTML(open(url))
rescue Net::OpenTimeoutError => e
raise CustomError, e.message
end
推荐阅读
- python - 如何从一个范围内获得两个不同的随机样本
- php - 将任意属性附加到 Blade x 组件,绑定属性à la Vue.js
- r - 如果在字符向量元素中找不到正则表达式匹配,如何返回 NULL?
- ios - 如果一个发布者没有产生任何值,如何让 CombineLatest3 返回结果?
- android - 为什么 Android Studio 中的 Image Asset 工具不会为 xxxhdpi 文件夹生成 PNG 文件?
- uwp - 如何使用 Windows Cloud Sync Engine API 支持删除?
- java - 需要从使用 java 3.12.0 驱动程序的 java 应用程序中的 mongoDB Atlas 中获取具有相同 first_name 的客户的 customerID 列表
- python - 为什么我的表单没有保存到管理数据库?
- python - 没有响应和程序冻结
- javascript - 无论值如何,如何从选择器中排除具有属性的元素