Created
August 8, 2012 14:14
-
-
Save tekei/3295352 to your computer and use it in GitHub Desktop.
instapaper文字化け再登録ツール (エッセンス版)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# instapaper文字化け再登録ツール (エッセンス版) | |
# 利用にはOauthキーが必要ですので、Webサービス化する予定です。 | |
# | |
# 利用に関して | |
# ・ 修正したRead Laterは、再登録するため登録日付が「今」に変更されます。 | |
# (表示順が逆転します) | |
# ・ 有料会員である必要があります | |
# (InstapaperのFull APIの利用規約がそうなっている) | |
require 'open-uri' | |
require 'resolv-replace' | |
require 'timeout' | |
require 'charlock_holmes' | |
require 'active_support/core_ext' | |
# use https://github.com/mattb/instapaper_full | |
require 'instapaper_full' | |
OAUTH_KEY = 'xxxxxxxxx' | |
OAUTH_SECRET = 'xxxxxxxxxx' | |
username = '[email protected]' | |
password = 'xxxxxxx' | |
ip = InstapaperFull::API.new :consumer_key => OAUTH_KEY, :consumer_secret => OAUTH_SECRET | |
ip.authenticate(username, password) | |
module CorrectHelper | |
module_function | |
def scraping_title(url) | |
begin | |
html = "" | |
timeout(5){ | |
option = {'User-Agent' => 'Mozilla/4.0 (compatible; MSIE 8.0)'} | |
option[:ssl_verify_mode] = OpenSSL::SSL::VERIFY_PEER | |
option[:ssl_ca_cert] = "#{File.dirname(__FILE__)}/ca-bundle.crt" | |
html = open(url, option) { |c| c.read } | |
} | |
title = html.delete("\n\r")[/<title>(.*)<\/title>/i, 1].strip | |
return nil if title.blank? | |
encoding = CharlockHolmes::EncodingDetector.detect(html)[:encoding] | |
title.encode("UTF-8", encoding) | |
rescue => e | |
$stderr.puts "[scraping_title] HTTP Error = #{e.inspect}" | |
nil | |
end | |
end | |
def valid_check(url, title) | |
# instapaperの機能 private urlで登録したパターンは対象外にする | |
return nil unless url =~ /^https?:/ | |
urls = url.split('/') | |
# instapaperがタイトル取得をあきらめたパターン | |
return :retry if (urls.size > 3 && title == urls[-1]) | |
return :utf if valid_check_utf8(title) | |
return :sjis if valid_check_sjis(title) | |
end | |
# 本来、codepointsメソッドを利用した場合UCS-2の値が取得出来る。 | |
# この値がUTF-8の規則に合致している場合、異常が発生していると考えられる | |
def valid_check_utf8(str) | |
utf8_contain = false | |
pattern = 0 | |
pos = 0 | |
str.codepoints do |c| | |
if (c >= 0x00 && c <= 0x7f) then | |
return false if (pattern != 0) | |
elsif (c >= 0x80 && c <= 0xbf) then | |
return false if (pattern == 0) | |
utf8_contain = true | |
pos += 1 | |
pattern, pos = 0, 0 if (pos == pattern) | |
elsif (c >= 0xc2 && c <= 0xdf) then | |
return false if (pattern != 0) | |
pattern, pos = 1, 0 | |
elsif (c >= 0xe0 && c <= 0xef) then | |
return false if (pattern != 0) | |
pattern, pos = 2, 0 | |
elsif (c >= 0xf0 && c <= 0xf7) then | |
return false if (pattern != 0) | |
pattern, pos = 3, 0 | |
else | |
return false | |
end | |
end | |
return (utf8_contain && (pattern == 0) && (pos == 0)) | |
end | |
# SJISっぽいかチェックする | |
def valid_check_sjis(str) | |
sjis_contain = false | |
upper_code = true | |
str.codepoints do |c| | |
return false if c >= 0x100 | |
if upper_code then | |
if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xef)) then | |
upper_code = false | |
end | |
else | |
if ((c >= 0x40 && c <= 0x7e) || (c >= 0x80 && c <= 0xfc)) then | |
sjis_contain = true | |
upper_code = true | |
else | |
return false | |
end | |
end | |
end | |
return sjis_contain | |
end | |
end | |
# read later直下のみ対応。 | |
ip.bookmarks_list(:limit => 100).each do |b| | |
if b['type'] == 'bookmark' then | |
correct_type = CorrectHelper::valid_check(b['url'], b['title']) | |
unless correct_type.nil? | |
puts "URL : #{b['url']}" | |
puts "元のタイトル : #{b['title']}" | |
correct_title = nil | |
case correct_type | |
when :utf then | |
correct_title = b['title'].codepoints.to_a.pack("C*").force_encoding('utf-8') | |
when :sjis then | |
correct_title = b['title'].codepoints.to_a.pack("C*").force_encoding('windows-31j').encode("utf-8") | |
else | |
correct_title = CorrectHelper::scraping_title(b['url']) | |
# 実処理では、scraping_titleの値はキャッシュを行っています。 | |
end | |
puts "正しそうなタイトル : #{correct_title}" | |
ip.bookmarks_add(:url => b['url'], :title => correct_title, :description => b['description']) | |
end | |
end | |
end | |
puts "変換できました!" |
現状で発生を確認しているパターンに対応。
EUC, JISに対する文字化けは確認出来ていない。
なお、ほとんどが「valid_check_utf8」パターンでの文字化け。
Webサービスとして、公開しました。
https://correct.herokuapp.com/
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
iso-8859-1で記述されたフランス語サイトで誤変換が発生したり、
また、Intrapaperがタイトル取得をあきらめたパターンに対応