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にデプロイしてもいいかもしれない。

何かありましたらコメントをどうぞ

comments powered by Disqus

人気の記事

950 Points チリ出身のギタリストが弾くドラゴンボールZがむちゃくちゃかっこいい…
774 Points Wordpress + Heroku + PostgreSQL + Amazon S3 = ¥0 / 無料でサイト運営
700 Points Rubyのチートシート 変数 / クラス / モジュール
524 Points Rubyのチートシート / アクティブサポート
451 Points 紙のデザイナーがウェブ開発できるようになるまでに必要なこと
435 Points Rails / Google Analyticsのデータを使って分析や管理画面のためのグラフをつくる
323 Points RailsとHerokuでノーティフィケーションをプッシュする / PusherとTurbolinksの兼ね合い
222 Points Rails / RSpec テスト書いたことない メンドクサイ(n´Д`)という時のチートシート
193 Points Rails / Ajaxを使って画面遷移しない一時保存機能をつける
193 Points Protractorでスクレイピングしてみた