我正在研究一个宝石。 这是它的主页: https://github.com/scaryguy/vakit
如果您查看源代码,您可以看到我正在解析外部HTML页面以从中过滤一些数据。
问题是,尽管我每次拨打Vakit.sabah
或Vakit.oglen
新请求时都会通过一个请求获取我想要的所有数据。
require "vakit/version"
require 'vakit/connect'
require 'Nokogiri'
require 'open-uri'
module Vakit
def self.today
Vakit::Connect.shaber
end
def self.imsak
Vakit::Connect.shaber[:imsak]
end
def self.sabah
Vakit::Connect.shaber[:sabah]
end
def self.oglen
Vakit::Connect.shaber[:oglen]
end
def self.ikindi
Vakit::Connect.shaber[:ikindi]
end
def self.aksam
Vakit::Connect.shaber[:aksam]
end
def self.yatsi
Vakit::Connect.shaber[:yatsi]
end
end
我认为这不是一种有效的方式。
我应该能够在没有新请求的情况下访问我的哈希的属性,不应该吗?
module Vakit
class Connect
def initialize(opt={})
@path = opt[:path]
end
def self.shaber
doc = Nokogiri::HTML(open('http://www.samanyoluhaber.com/'))
x = doc.css('#hnmzT')
times = []
x.each do |vakit|
data = vakit.children.first.children.last.content
data_add = data.slice(0..data.length-2)
times.push(data_add)
end
times
vakit = {
imsak: times[0],
sabah: times[1],
oglen: times[2],
ikindi: times[3],
aksam: times[4],
yatsi: times[5]
}
end
end
end
我需要一些启发。
答案 0 :(得分:1)
每次使用shaber
时,您都明确open
并重新分析内容。您没有尝试本地存储内容或解析的DOM,并检查您是否已经拥有它。
而不是doc =
使用@@doc ||=
并将doc
的出现次数更改为@@doc
。
||=
运算符仅在@@doc
为空时分配。一旦它被分配到非零或非假值,它将不再触发,因此它是一个穷人“记忆”。
因为您使用的是类方法,所以我建议使用类变量。如果您有多个正在查看不同页面的类实例,@@doc
可能是实例变量@doc
。原样,这不会产生任何影响,因为您只对一个页面进行了硬编码,但对于未来的代码增长,它可能会有用。
您为访问该页面而编写的代码并不是非常惯用的Ruby。我写的更像是以下内容,因为URL没有返回具有足够时间值的页面,所以它不起作用:
require 'nokogiri'
require 'open-uri'
module Vakit
URL = 'http://www.samanyoluhaber.com/'
class Connect
def initialize(opt={})
@path = opt[:path]
@url = opt[:url] || URL
end
def shaber(url=nil)
doc = Nokogiri::HTML(open(url || @url))
doc.at_css('#hnmzT').to_html # => "<li id=\"hnmzT\" name=\"imsak\"><a id=\"at\"><span>\u0130msak:</span>4:22\u00A0</a></li>"
x = doc.at_css('li#hnmzT a')
x.to_html # => "<a id=\"at\"><span>\u0130msak:</span>4:22\u00A0</a>"
times = x.text.scan(/\d+:\d+/)
Hash[[:imsak, :sabah, :oglen, :ikindi, :aksam, :yatsi].zip(times)]
end
end
end
connection = Vakit::Connect.new
connection.shaber # => {:imsak=>"4:22", :sabah=>nil, :oglen=>nil, :ikindi=>nil, :aksam=>nil, :yatsi=>nil}
Connect
不是一个好名字。一个类是一个对象,一个东西。 Connect
是动词,是事物发生或发生的事情。 connect
对于方法来说是一个好名字。
答案 1 :(得分:0)
这一行
doc = Nokogiri::HTML(open('http://www.samanyoluhaber.com/'))
正在多次拨打请求的电话。
我用你的宝石测试了这个,这似乎有效。
if @doc.nil?
@doc = Nokogiri::HTML(open('http://www.samanyoluhaber.com/'))
end
另外在vakit.rb中更改
require 'Nokogiri' to require 'nokogiri'
(简单n)
答案 2 :(得分:0)
我将提出以下建议:
Vakit::Connect
应该是类中的实例方法。所以它可以实例化&amp;保存在记忆中。这样每个请求将是同一对象的不同实例。如果班级不存在。创造它。memorization
来缓存代价高昂的操作。 所以我会这样做: 连接类:
module Vakit
class Connect
attr_accessor :path, :doc
def initialize(opt={}, url)
@path = opt[:path]
@doc = Nokogiri::HTML(open(url))
end
def shaber
x = @doc.css('#hnmzT')
#no changes here
end
end
Vakit模块
module Vakit
class Main #name it something more meaningful
def initialize(opt={})
@connected = Connect.new(opt[:path], 'http://www.samanyoluhaber.com/')
end
def today
@connected.shaber
end
def imsak
today[:imsak]
end
def sabah
today[:sabah]
end
def oglen
today[:oglen]
end
def ikindi
today[:ikindi]
end
def aksam
today[:aksam]
end
def yatsi
today[:yatsi]
end
end
然后在代码中,您可以像这样使用它:
@v = Vakit::Main.new
@v.aksam
这可能不是100%完美,因为我真的不明白你的代码的目的,哦明白它的作用但不是为什么。但是每次访问哈希时,这都不会产生新的请求。