【问题标题】:How check correct url protocol in ruby?如何在 ruby​​ 中检查正确的 url 协议?
【发布时间】:2014-07-28 22:43:40
【问题描述】:

我有 50,000 个网站的列表,我想知道他们有什么样的协议。我拥有的所有网站都有所有 names.com 或 like something.com,但没有一个有 http://google.com。我确实尝试过运行 each 并手动检查..

require 'rubygems'

require 'open-uri'
require 'io/console'
require 'open_uri_redirections'
require 'openssl'

OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE



filename = "./testfile.txt"
destination = File.open("./11aa.txt", "a")

newArray = Array.new
newArray = IO.readlines(filename)
newArray.each do |url|
begin
    puts "#{url}"
    if open(url,:read_timeout=>2 )
        destination.write "#{url}"      
    end

rescue => e
  puts e.message
end
    end

确实有效,但需要很长时间才能完成。我正在寻找更好的算法来检查。

谢谢

【问题讨论】:

  • “协议”是什么意思?用于 URL 的 IP 协议?
  • 我的意思是方案“http”或“https”。我不想错过任何网站,所以我需要检查该网站是否存在。然后我需要在上面运行海葵刮刀。所以我必须事先决定。

标签: ruby-on-rails ruby open-uri


【解决方案1】:

“协议”?与用于连接到由 URL 定义的主机的 IP 协议一样吗?

require 'uri'

URI.parse('http://foo.com').scheme # => "http"
URI.parse('https://foo.com').scheme # => "https"
URI.parse('ftp://foo.com').scheme # => "ftp"
URI.parse('scp://foo.com').scheme # => "scp"

如果您想知道一个站点是否接受 HTTPS 还是 HTTP,我会从检查 HTTPS 开始,因为大多数站点都允许 HTTP:

require 'net/http'

%w[
  example.com
  www.example.com
  mail.google.com
  account.dyn.com
].each do |url|
  begin
    Net::HTTP.start(url, 443, :use_ssl => true) {}
    puts "#{url} is HTTPS"
  rescue
    puts "#{url} is HTTP"
  end
end
# >> example.com is HTTP
# >> www.example.com is HTTP
# >> mail.google.com is HTTPS
# >> account.dyn.com is HTTPS

尽管 mail.google.com 和 account.dyn.com 是 HTTPS,但如果您首先测试它们的 HTTP,您会发现它们也具有该协议。一些网站会将他们的 HTTP 请求重定向到他们的 HTTPS 服务器,而另一些网站则同时运行以允许用户决定他们想要 HTTP 还是 HTTPS。您可以测试这两种协议以确定哪些情况是正确的。

start 不需要块,但通过提供一个空块,它会在建立连接后立即自动关闭连接。

站点不一定在端口 80 和 443 上运行其 Web 服务。因此,假设连接到这些端口之一不一定正确,如果它们使用不同的端口,可能会给您带来不好的结果。 8080 和 8081 也经常使用,所以也应该检查一下。

此外,网站可能会在端口上做出响应,但其内容可能是将您指向他们希望您使用的真实端口的重定向,因此您还需要考虑是否应该只关心连接是否成功,或者查看在 HTTPd 标头中,或者实际读取返回的整个页面,并在它是软件重定向的情况下对其进行解析。

换句话说,成功的连接并不能充分告诉您网站希望您使用什么,您还必须进行额外的测试。

【讨论】:

    【解决方案2】:

    您最关心哪种协议? HTTPS 比 HTTP 更可取吗?有些两者都有,有些是重定向(http://www.google.com 是 302)

    如果你不在乎它是哪一个,那么首先使用 http,因为它可能更有可能,所以调用它应该会快得多。

    另外,我会将 read_timeout 降低到 1 甚至 500 毫秒。如果一个网站在这段时间内没有响应,它可能已经死了(我们说的是一个简单的响应,没有完全下载 DOM 的所有资产)。

    【讨论】:

    • 有道理,我用了你的想法。
    【解决方案3】:

    需要'open-uri'

    def correct_url_protocol(single_url)
        puts "-----------------------In correct_url_protocol--------------------------"
    
            begin
             good_link = "http://www.#{single_url}"
                if open(good_link, read_timeout: 3,:allow_redirections => :all)
                    "http://www.#{single_url}"
                else 
                    "https://www.#{single_url}"
                end 
            rescue => e
                exp = e.message
                if exp.match("redirection forbidden")
                    good_link = "https://www.#{single_url}"
                    good_link
    
                    end
                puts e.message
                good_link
            end 
    end
    

    我认为这是我创建的最佳方法。让我知道是否更好。

    【讨论】:

    • 您假设一个站点以www. 开头,这不是一个有效的假设。您还假设站点名称尚未以它开头,这又不是一个安全的假设。很多站点会自动重定向到它们的 www 等效站点,但仍有一些站点没有 www 前缀,例如 Stack Overflow。此外,如果您不能 open 连接,则假设连接是 https,但除非您测试它是否确实存在,否则这是无效的。
    • 不要做exp.match("redirection forbidden")。而是使用e.message["redirection forbidden"],它更快并且完成同样的事情。
    • @theTinMan 您对 www 重定向是正确的,如果是这种情况,那么当我调用 open(good_link, read_timeout: 3,:allow_redirections => :all) 时它应该可以工作。我认为这个 allow_redirection => all 是这里的关键。这又是我的主要问题之一。太奇怪了,外面没有这样的东西。当我有一些时间时,我想为它创造宝石。再次感谢您的意见。
    • 我不知道你为什么关心他们支持什么协议。如果您处理重定向,它将成为一个有争议的问题;查看他们重定向到的 URL,并在必要时启用 SSL。或者,仅仅依靠 OpenURI 来处理事情。
    猜你喜欢
    • 1970-01-01
    • 2011-06-23
    • 2012-11-14
    • 2015-08-15
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多