2

このページをスクレイピングしようとしています: http://www.udel.edu/dining/menus/russell.html . Hpricot ライブラリを使用して、Ruby でスクレイパーを作成しました。

問題: HTML ページがエスケープされており、エスケープせずに表示する必要がある

example: "M&M" should be "M&M"  
example: "Entrée" should be "Vegetarian Entrée"  

Ruby の CGI ライブラリ (あまり成功していません) と、このスタック オーバーフローの投稿で見つけた HTMLEntities gem を使用してみました。

HTMLEntities はテスト中に機能します。

require 'rubygems' 
require 'htmlentities'
require 'cgi'

h = HTMLEntities.new
puts "h.decode('Entrée') = #{h.decode("Entrée")}"

blank = " "
puts "h.decode blank = #{h.decode blank}"
puts "CGI.unescapeHTML blank = |#{CGI.unescapeHTML blank}|"

puts "h.decode '<th width=86 height=59 scope=row>Vegetarian Entr&eacute;e</th> ' = |#{h.decode '<th width=86 height=59 scope=row>Vegetarian Entr&eacute;e</th> '}|"  

正しく利回り

h.decode('Entr&eacute;e') = Entrée
h.decode blank =  
CGI.unescapeHTML blank = |&nbsp;|
h.decode '<th width=86 height=59 scope=row>Vegetarian Entr&eacute;e</th> ' = |<th width=86 height=59 scope=row>Vegetarian Entrée</th> |

ただし、open-uri を使用してファイルで使用すると、正しく動作しません。

require 'rubygems'
require 'hpricot'
require 'open-uri'
require 'htmlentities'
require 'cgi'
f = open("http://www.udel.edu/dining/menus/russell.html")
htmlentity = HTMLEntities.new
while line = f.gets
  puts htmlentity.decode line
end

次のようなものを誤って生成します。

<th width="60" height="59" scope="row">Vegetarian Entrée</th>

<th scope="row"> </th>  // note: was originally '&nbsp;' to indicate a blank

しかし、M&M は次のように正しく処理されます。

<td valign="middle" class="menulineA">M&M Brownies</td>

エスケープされた HTML を正しく処理していませんか? なぜそれが機能する場合と機能しない場合があるのか​​ わかりません。

Ruby 1.8.7 (2009-06-12 パッチレベル 174) [i486-linux] を実行しています。

どんな助け/提案も大歓迎です。ありがとう。

4

1 に答える 1

0

HTMLEntities は機能しているように見えますが、エンコードに問題があります。印刷している端末は、おそらく、スクリプトによって出力される utf-8 文字のラテン文字セットと barfs 用に設定されています。

ruby はどの環境で実行していますか?

「&」が正しく表示される理由は、これがアスキー文字であるため、ほとんどのエンコーディングで同じように表示されるためです。問題は、xml ドキュメントで単独で発生することは想定されておらず、後でデコードされたファイルを hpricot にフィードするときに問題が発生する可能性があることです。 . hpricot で解析し、ドキュメントから抽出したものを HTMLEntity に渡すのが適切な方法だと思います。

于 2010-05-11T06:12:43.777 に答える