LoginSignup
3
3

More than 5 years have passed since last update.

Nokogiri で DOM の切った貼ったメモ

Last updated at Posted at 2019-01-21

備忘録ですが何かの役に立てればと思って公開します。DOM の切り貼りがメインです。Nokogiri でスクレイピングができる人が対象です。スクレイピングに使いたい人はぐぐればたくさん例が出てくるのでこんな読みづらいメモを読んで時間を無駄にすることはないと思います :smile:

備忘録ですので随時内容の修正、追加をおこないます。

準備

bundler を使って nokogiri のインストールをするというよくあるやつです。

  • 適当なディレクトリを作って移動
  • 必要なら rbenv とかで ruby のバージョンをどうのとかやる
  • $ bundle init で Gemfile を生成
  • Gemfile 末尾に gem "nokogiri" の行を付け加える
  • $ bundle install --path=.bundle/vendor/bundle

ここまでで Nokogiri がインストールされ使えるようになりました。続いて初期のコードです。

#!/usr/bin/env ruby
require 'bundler'
Bundler.setup(:default, :ci)
require 'nokogiri'

RAW_HTML = DATA.read # __END__ の次行から末尾まで読み込む

def get_document
  Nokogiri::HTML(RAW_HTML, nil, 'utf-8')
end

__END__
<html>
<head>
<title>hello</title>
</head>
<body>
<p>hello</p>
<p id="foo">goto <a href="https://qiita.com">Qiita</a> site!</p>
</body>
</html>

以後この get_document で Nokogiri::HTML::Document を生成してからコード例を挙げていきます。いちいち生成し直すのは紹介するメソッドの殆どが破壊的メソッドだからです。なおコード例は __END__ の前に記述してください。

例題

内容の変更

doc = get_document
doc.at_css('title').content = 'new title'
puts doc.at_css('title') # => '<title>new title</title>'

# #foo の子供の最初のノード (goto ) を書き換える
doc.at_css('#foo').children[0].content = 'this is '
puts doc.at_css('#foo') # => '<p id="foo">this is <a href="https://qiita.com">Qiita</a> site!</p>'

ただし Nokogiri::XML::Text#content= にタグつきの文字列を渡してもエスケープされてしまいます。

メソッド cssat_css の違いについて

スクレイピング方面の話題ですが、よく忘れるので。ノード (要素) を CSS セレクタで特定する二種類のメソッドがあります1

doc = get_document
p doc.css('p').map{|x| x.to_s} # => ["<p>hello</p>", "<p id=\"foo\">goto <a href=\"https://qiita.com\">Qiita</a> site!</p>"]
puts doc.at_css('p').to_s # => <p>hello</p>

要は

  • Nokogiri::XML::Searchable#css は条件に合致する要素をすべてリストアップする
  • Nokogiri::XML::Searchable#at_css は条件に合致した最初の要素を返す

ということです。id 属性で取り出すときなんかはドキュメント中にひとつしかないので at_css で取るとよいかと思います。

特定要素の内容をごっそり入れ替える

doc = get_document
doc.at_css('#foo').children.unlink
doc.at_css('#foo') << '<span>new text</span>'
puts doc.at_css('#foo') # => '<p id="foo"><span>new text</span></p>'

こちらはタグが使えます。ちなみに Nokogiri::Node#<< メソッドは要素の内容の末尾に付け加えるものです。なので最初の行の 〜.children.unlink がなければ、「site!」の後ろに span 要素が挿入されることになります。やってみるとわかると思います。

参考文献


  1. xpath で指定する方法もあるようですがが使ったことがありません。 

3
3
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3