OpenURIで取得したデータをDBに入れる際のエラー / invalid byte sequence for encoding “UTF8”
Nokogiriでスクレイピングは楽しいんですが、.xpathや.cssメソッドに渡す引数を割り出すのに、けっこう時間がかかったりする。その度にirbで接続するのもなんなのでDBに保存しとくことにした。
パースの練習がしたいだけなので、パースした後のデータを保存するのではなくて、パース前のナマのデータを保存したい。
ところがDBに保存するときにエラーがでましたよと。
ruby
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class TestContentController < ApplicationController
require 'open-uri'
def create
url = "http://www.yourwebsite_here.com"
html = open(url).read
TestContent.create( content: html )
end
end
# => TestContent.createメソッドでエラー
# invalid byte sequence for encoding “UTF8”
UTF8では扱えないinvalidな文字があるよということなんだろうけど、どう変換していいのか悩んだ。
ちなみにvalidかinvalidかはStringクラスのvalid_encoding?で調べられる。
html = open(url).read で取得した時のエンコードは"ASCII-8BIT"だった。
1
2
html.encoding.name
=> "ASCII-8BIT"
いろいろやってみたけど、一度SJISに変換してからUTF-8に変換するという回りくどいやり方でとりあえずは保存できました。
ruby
1
2
3
4
5
6
7
html = html.encode( 'SJIS', invalid: :replace, undef: :replace, replace: '' )
html = html.encode( 'UTF-8', invalid: :replace, undef: :replace, replace: '' )
html.valid_encoding?
# => true
扱えない文字を''で置き換えているので、元のデータとは若干違うところもあるかもしれませんが、パースの練習用にはとりあえずこれで十分。
ruby
1
2
3
4
5
6
7
8
require 'nokogiri'
test_content = TestContent.first.content
parsed = Nokogiri::HTML(test_content)
parsed.css("#my_main_content > .left_column > ul li:first-child").text
# => 目的のテキスト
時間を短縮するための試みだったのに、逆に時間がかかってしまった。
悔しいので「Nokogiriテスター」なるものを作ったらもの凄く便利だ…。
暇ができたらherokuにデプロイしてもいいかもしれない。