随机代理不起作用



我有一个名为代理的模型,我在其中存储我的代理。

我希望Nokogiri每次打开网页时都能使用IP和端口获取随机代理。

这是我的代码:

total_proxies = @proxies.count
random_proxies = rand(total_proxies - total_proxies..total_proxies -1)
doc = Nokogiri::HTML(open(page.uri, :proxy => '#{random_proxies.ip}:#{random_proxies.port}'))

我在这里错过了什么?当我尝试运行它时,给我这个错误:

bad URI(is not URI?): #{random_proxies.ip}:#{random_proxies.port}

你正在使用单引号作为字符串参数来:p roxy。 您需要双引号,以便对#{}进行插值。 这样:

doc = Nokogiri::HTML(open(page.uri, :proxy => "#{random_proxies.ip}:#{random_proxies.port}"))

我想让 nokogiri 获取一个随机代理...

你不明白Nokogiri是如何工作的。它什么也没得到。曾。它可以读取打开的文件,也可以接受字符串,但它不知道如何"获取"任何内容。

这项工作落在代码中的 OpenURI 上,它修补内核的 open 方法来理解 URL。OpenURI将打开的文件返回给Nokogiri,然后从中读取。因此,这使Nokogiri摆脱了获取任何东西的问题。读取错误

bad URI(is not URI?)

更仔细地,你会发现它来自OpenURI,而不是Nokogiri。

正如@PhilipHallstrom所说(给他功劳,而不是我),真正的问题是你使用单引号而不是双引号来包装你的内插字符串。考虑一下:

class RandomProxies
  def ip 
    '127.0.0.1'
  end
  def port
    42
  end
end
random_proxies = RandomProxies.new
'#{random_proxies.ip}:#{random_proxies.port}'
# => "#{random_proxies.ip}:#{random_proxies.port}"
"#{random_proxies.ip}:#{random_proxies.port}"
# => "127.0.0.1:42"

。如果我没错,请纠正我 dosen open-uri 关闭连接。因为在它为每个页面打开代理后,我收到此错误"503 打开的连接太多"。

不,Nokogiri 不会关闭连接;我真的不认为这是它的责任。

您可以查看parseread_io源代码来确认这一点,并且/或者,如果您使用的是Linux,则可以运行一些测试:

  1. 在磁盘上创建一个简单的 XML 文件。
  2. 启动 IRB 并加载 Nokogiri:

    require 'nokogiri'
    
  3. 告诉 Nokogiri 使用以下方法解析文档:

    Nokogiri::XML(open('path/to/file.xml'))
    
  4. 切换到另一个 shell 中的命令行并运行:

    lsof | grep path/to/file.xml
    

    lsof命令将显示 Ruby 仍然打开该文件,尽管 Nokogiri 读取了它。("LSOF"代表"列出打开的文件")。

  5. 退出 IRB 并再次运行 lsof 命令。您将看到它已关闭,因为文件未显示。

遇到问题的原因是因为您正在打开一堆文件而不是关闭它们。通常/通常我们可以不关闭它们,因为有大量可用的文件句柄,并且代码在退出之前不会耗尽这些句柄。但这并不是真正的好编程实践。我们应该显式关闭它们,或者依赖于在完成后关闭文件的方法/结构。

因为您正在使用 Nokogiri 将文件解析为 DOM,所以 Nokogiri 会将整个文件读入内存进行处理。在这种情况下,不要简单地使用 open ,请使用 open 后跟 read,完成后将关闭文件。从文档中:

读取确保文件在返回之前已关闭。

或者,您可以将文档的分析(无论是文件还是从网络 URL 读取)放入块中,以便自动关闭。像这样未经测试的代码应该可以工作:

require 'open-air'
%w[urls to read].each do |url|
  open(url) do |xml|
    dom = Nokogiri::XML(xml) 
    # do something with the dom
  end
end

请记住,使用带有open的块可确保在块退出时自动关闭文件。

如果指定了块,则将以 IO 对象作为参数调用该块,并且当块终止时,IO 将自动关闭。调用返回块的值。

这应该可以防止"503 打开的连接过多"问题发生,因为您的代码一次只能打开一个与主机的连接。

如果您请求的页面数已经用完了,另一种解决方案是使用 Typhoeus 和 Hydra,它们可以并行抓取 URL,并且可以被告知如何限制连接。(您将请求限制在合理的价格,不是吗?如果没有,你应该得到503错误。

相关内容

  • 没有找到相关文章

最新更新