2

私はノコギリを使ってさまざまな国に関するウィキペディアのページを開き、インターウィキリンク(外国語のウィキペディアへのリンク)から他の言語でこれらの国の名前を抽出しています。しかし、フランスのページを開こうとすると、のこぎりは全ページをダウンロードしません。多分それは大きすぎます、とにかくそれは私が必要とするインターウィキリンクを含んでいません。どうすればすべてを強制的にダウンロードできますか?

これが私のコードです:

url = "http://en.wikipedia.org/wiki/" + country_name
page = nil
begin
  page = Nokogiri::HTML(open(url))
rescue   OpenURI::HTTPError=>e
  puts "No article found for " + country_name
end

language_part = page.css('div#p-lang')

テスト:

with country_name = "France"
=> []

with country_name = "Thailand"
=> really long array that I don't want to quote here,
   but containing all the right data

たぶん、この問題はNokogiriを超えてOpenURIにまで及ぶでしょう-とにかく私は解決策を見つける必要があります。

4

3 に答える 3

9

Nokogiriはページを取得せず、readOpen::URIが返すStringIOオブジェクトの内部で検索するようにOpenURIに要求します。

require 'open-uri'
require 'zlib'

stream = open('http://en.wikipedia.org/wiki/France')
if (stream.content_encoding.empty?)
  body = stream.read
else
  body = Zlib::GzipReader.new(stream).read
end

p body

キーオフできるものは次のとおりです。

>> require 'open-uri' #=> true
>> open('http://en.wikipedia.org/wiki/France').content_encoding #=> ["gzip"]
>> open('http://en.wikipedia.org/wiki/Thailand').content_encoding #=> []

この場合[]、別名「text / html」の場合は、次のようになります。["gzip"]デコードする場合。

上記のすべてのことを行い、それを次のように投げます:

require 'nokogiri'
page = Nokogiri::HTML(body)
language_part = page.css('div#p-lang')

軌道に戻るはずです。

上記のすべての後にこれを実行して、使用可能なものが得られていることを視覚的に確認します。

p language_part.text.gsub("\t", '')

2つの異なる結果が表示された理由については、Casperの回答とコメントを参照してください。元々、Open-URIは返されたデータの処理に一貫性がないように見えましたが、Casperの発言と、curlを使用して見たものに基づくと、Wikipediaは大きなドキュメントの「Accept-Encoding」ヘッダーを尊重せず、gzipを返します。これは今日のブラウザではかなり安全ですが、エンコーディングを自動的に感知しないOpen-URIのようなクライアントには問題があります。上記のコードが修正に役立つはずです。

于 2011-07-02T20:33:14.710 に答える
0

かなりの頭をかいた後、問題はここにあります:

> wget -S 'http://en.wikipedia.org/wiki/France'
Resolving en.wikipedia.org... 91.198.174.232
Connecting to en.wikipedia.org|91.198.174.232|:80... connected.
HTTP request sent, awaiting response...
  HTTP/1.0 200 OK
  Content-Language: en
  Last-Modified: Fri, 01 Jul 2011 23:31:36 GMT
  Content-Encoding: gzip <<<<------ BINGO!
  ...

gzipで圧縮されたデータを解凍する必要がありますが、open-uriは自動的に解凍しません。
解決:

def http_get(uri)
  url = URI.parse uri

  res = Net::HTTP.start(url.host, url.port) { |h|
    h.get(url.path)
  }

  headers = res.to_hash
  gzipped = headers['content-encoding'] && headers['content-encoding'][0] == "gzip"
  content = gzipped ? Zlib::GzipReader.new(StringIO.new(res.body)).read : res.body

  content
end

その後:

page = Nokogiri::HTML(http_get("http://en.wikipedia.org/wiki/France"))
于 2011-07-02T20:12:31.367 に答える
0
require 'open-uri'
require 'zlib'

open('Accept-Encoding' => 'gzip, deflate') do |response|
  if response.content_encoding.include?('gzip')
    response = Zlib::GzipReader.new(response)
    response.define_singleton_method(:method_missing) do |name|
      to_io.public_send(name)
    end
  end

  yield response if block_given?

  response
end
于 2013-07-08T17:40:58.537 に答える