そこらへんで拾ってきたHTMLをNokogiriに渡すと,文字化けすることがあって,困ってた.
Nokogiriに文字コードを渡せるので,HTMLから正規表現でcharsetを取り出して,一番多く出現するcharsetをそのページのcharsetとして採用すると,うまくいった.
ヒューリスティックにやってるだけだけど,だいたいうまくいく.
こんな感じ.
charset = io.scan(/charset="?([^\s"]*)/i).flatten.inject(Hash.new{0}){|a, b| a[b]+=1 a }.to_a.sort_by{|a| a[1] }.reverse.first[0]
before
"〓\u0082«〓\u0083¼〓\u0083\u0089〓\u0083\u0095〓\u0082〓〓\u0082〓〓\u0083\u0088!! 〓\u0083´〓\u0082〓〓\u0083³〓\u0082¬〓\u0083¼〓\u0083\u0089〓\u0080\u0080〓¬¬6〓〓±〓\u0080\u008C〓¬\u008E〓\u0081〓〓\u0082«〓\u0083¼〓\u0083\u0089〓\u0082·〓\u0083§〓\u0083\u0083〓\u0083\u0097〓\u0080\u008D 〓\u0080\u0090 〓\u0083\u008B〓\u0082³〓\u0083\u008B〓\u0082³〓\u008B\u0095〓\u0094»(〓\u008E\u009F〓〓〓)"
after
"カードファイト!! ヴァンガード 第6話「謎のカードショップ」 ‐ ニコニコ動画(原宿)"
https://gist.github.com/827022
# -*- coding: utf-8 -*- require 'open-uri' require 'nokogiri' def before(url) io = URI.parse(url).read Nokogiri(io) end def after(url) io = URI.parse(url).read charset = io.scan(/charset="?([^\s"]*)/i).flatten.inject(Hash.new{0}){|a, b| a[b]+=1 a }.to_a.sort_by{|a| a[1] }.reverse.first[0] Nokogiri(io, url, charset) end puts 'before' p before('http://www.nicovideo.jp/watch/1297306177').at('title').content puts 'after' p after('http://www.nicovideo.jp/watch/1297306177').at('title').content
追記
この方法だとはてなグループがEUC-JPだと思われてしまう.文字コードのちがう,よそのウェブサービスのJavaScriptを読みこんでると,こうなる.困った.
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <link rel="stylesheet" href="/diary_css/base.css" type="text/css" media="all" charset="euc-jp"> <link rel="stylesheet" href="/theme/hatena/hatena.css" type="text/css" media="all" charset="euc-jp"> <script type="text/javascript" src="http://d.hatena.ne.jp/js/quick_pager.js" charset="euc-jp"></script>
追記
require "open-uri" ; open(url).charset はどうでしょう http://rurema.clear-code.com/1.9.2/library/open=2duri.html
はてなブックマーク - sonota88のブックマーク - 2011年2月16日
open-uriのcharsetは,だいたい合っていて,よい感じだけど,ニコニコ動画がiso-8859-1になったりしてしまう.
ので,open-uriのcharsetがiso-8859-1じゃないときはcharsetを適当に探して使う,ということにした.
id:sonota88さんありがとうございます.
def after(url) io = URI.parse(url).read charset = io.charset if charset == "iso-8859-1" charset = io.scan(/charset="?([^\s"]*)/i).flatten.inject(Hash.new{0}){|a, b| a[b]+=1 a }.to_a.sort_by{|a| a[1] }.reverse.first[0] end Nokogiri(io, url, charset) end
before
# "〓\u0082«〓\u0083¼〓\u0083\u0089〓\u0083\u0095〓\u0082〓〓\u0082〓〓\u0083\u0088!! 〓\u0083´〓\u0082〓〓\u0083³〓\u0082¬〓\u0083¼〓\u0083\u0089〓\u0080\u0080〓¬¬6〓〓±〓\u0080\u008C〓¬\u008E〓\u0081〓〓\u0082«〓\u0083¼〓\u0083\u0089〓\u0082·〓\u0083§〓\u0083\u0083〓\u0083\u0097〓\u0080\u008D 〓\u0080\u0090 〓\u0083\u008B〓\u0082³〓\u0083\u008B〓\u0082³〓\u008B\u0095〓\u0094»(〓\u008E\u009F〓〓〓)"
after
"カードファイト!! ヴァンガード 第6話「謎のカードショップ」 ‐ ニコニコ動画(原宿)"
before
"復讐 - eigokunの手記 - - -"
after
"復讐 - eigokunの手記 - - -"