質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

RubyGems

RubyGemsはRubyによるプログラミングのためのパッケージマネジメントツールです。ユーザはこれを使用することで、Rubyライブラリのダウンロードやアップデートや、依存関係の自動解決が可能になります。

Q&A

1回答

2253閲覧

mechanizeのスクレイピングでレコードが重複してしまう

退会済みユーザー

退会済みユーザー

総合スコア0

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

RubyGems

RubyGemsはRubyによるプログラミングのためのパッケージマネジメントツールです。ユーザはこれを使用することで、Rubyライブラリのダウンロードやアップデートや、依存関係の自動解決が可能になります。

0グッド

0クリップ

投稿2016/06/06 06:07

編集2022/01/12 10:55

http://ranking.bunkyodo.co.jp/rankings/detail/0000/4

コチラのページから、タイトル、出版社名を取得したいと考えています。

lang

1<div class="col-sm-6"> 2 <div class="col-sm-2"><span class="text-danger">第1位</span></div> 3 <div class="col-sm-4"> 4 <img src="/img/cover/9784047340893.jpg" class="img-responsive" style="max-height: 150px; " alt="オーバーロード 10 謀略の統治者" /> </div> 5 <div class="col-sm-6"> 6 <h5 class="">オーバーロード 10 謀略の統治者</h5> 7 <p class="">KADOKAW</p> 8 </div> 9</div> 10 11<div class="col-sm-6"> 12 <div class="col-sm-2"><span class="text-danger">第6位</span></div> 13 <div class="col-sm-4"> 14 <img src="/img/cover/9784763135070.jpg" class="img-responsive" style="max-height: 150px; " alt="コーヒーが冷めないうちに" /> </div> 15 <div class="col-sm-6"> 16 <h5 class="">コーヒーが冷めないうちに</h5> 17 <p class="">サンマーク出版</p> 18 </div> 19</div> 20 </div> 21 22以下略

コードは以下のとおりです。

lang

1class Bunkyodo_scraping 2 def self.bunkyodo_ranking 3 agent = Mechanize.new 4 page = agent.get("http://ranking.bunkyodo.co.jp/rankings/detail/0000/4") 5 books = page.search('.col-sm-6') 6 books.each do |book| 7 rank = book.search('.col-sm-2').inner_text 8 title = book.search('h5').inner_text 9 publisher = book.search('p').inner_text 10 ranking_data = Bunkyodo.new(title: title, rank: rank, publisher: publisher) 11 ranking_data.save 12 end 13 end

これをコンソールで実行すると、以下のような実行内容になります。

lang

1[62] pry(main)> Bunkyodo_scraping.bunkyodo_ranking 2 (0.2ms) BEGIN 3 SQL (0.3ms) INSERT INTO `bunkyodos` (`title`, `rank`, `publisher`, `created_at`, `updated_at`) VALUES ('オーバーロード 10 謀略の統治者', 0, 'KADOKAW', '2016-06-06 06:05:00', '2016-06-06 06:05:00') 4 (0.4ms) COMMIT 5 (0.1ms) BEGIN 6 SQL (0.3ms) INSERT INTO `bunkyodos` (`title`, `publisher`, `created_at`, `updated_at`) VALUES ('', '', '2016-06-06 06:05:00', '2016-06-06 06:05:00') 7 (0.7ms) COMMIT 8 (0.1ms) BEGIN 9 SQL (0.3ms) INSERT INTO `bunkyodos` (`title`, `rank`, `publisher`, `created_at`, `updated_at`) VALUES ('コーヒーが冷めないうちに', 0, 'サンマーク出版', '2016-06-06 06:05:00', '2016-06-06 06:05:00') 10 (0.4ms) COMMIT 11 (0.1ms) BEGIN 12 SQL (0.3ms) INSERT INTO `bunkyodos` (`title`, `publisher`, `created_at`, `updated_at`) VALUES ('', '', '2016-06-06 06:05:00', '2016-06-06 06:05:00') 13 14 15以下略 16

titieとpublisherがなぜか2回取得されてしまいます。

該当ページのHTMLに「.col-sm-6」が2つあることが問題かと思うのですが、
解決策をご教授ください。よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ご認識の通り「.col-sm-6」が2個ある(しかも入れ子になっている)ためです。
そこまで分かっているのであれば、CSSセレクタまたはXPathの指定を工夫されればよいかと思います。

当該ページのHTMLソースを見て思いついた方法のひとつは、「<div class="row"> の子要素 である <div class="col-sm-6">」を選択する方法です。

lang

1books = page.search('div.row > .col-sm-6')

もうひとつは「<div class="col-sm-6"> を子要素に持つ <div class="col-sm-6">」を選択する方法です。こちらはCSSセレクタでは無理だと思う(わたしは)ので、XPathでの指定となります。

lang

1books = page.search('//div[@class="col-sm-6"][div[@class="col-sm-6"]]')

ちなみに、上記いずれの場合も、ページの構造に依存して、ランキングが1位、6位、2位、7位、・・・ という順番で取得されます。

投稿2016/06/06 14:17

q1701

総合スコア274

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/06/06 20:36 編集

非常にわかりやすい解説ありがとうございます! ちなみに「ページの構造に依存して、ランキングが1位、6位、2位、7位、・・・ という順番で取得されます」というのは仰る通りでした…。このHTML構造だと、ランキングを順番通りに取得するのは難しいでしょうか?
q1701

2016/06/06 23:15

ranking_data を rank でソートした方が簡単だと思いますよ。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問