LoginSignup
0
0

More than 3 years have passed since last update.

Rubyスクレイピングで超絶楽をする(記事詳細ページ全件取得編)

Posted at

以前、ある案件で、
検索結果一覧にある全詳細ページの特定のタグ内にある内容が必要になったのですが、
その詳細ページに辿り着く方法が2パターンありました。

①エリアなどの検索条件指定して検索かけるなどして、辿り着く方法
②1ページずつリンクを直打ちして開く方法

たしか、全部で300ページくらいあったので、
スクレイピングして取得する事にしました。

どうやって全件取得するか?

検索条件を自動で入れて取ってくる方法を考えましたが、
複雑なことを考えるのは面倒だったので、シンプルに考えることにしました。
方法としては、
①本番と同じファイルを用意する。
②詳細ページがまるごと入っているディレクトリを見つける
③その詳細ページがあるディレクトリをスクレイピングして、ファイル名全件取得取得
④取得時にファイル名の前に本番のリンクをくっつける
⑤リンク先一覧として、CSVで吐き出す。

といった感じですかね。

スクレイピングで使用したソースコード

書いてあることは、上に書いてある内容です。
単純に、特定のディレクトリ内(article/)のファイル名を全件取得して、
本番のリンクを前に繋げてあるだけです。
これによって、本番サイトの全詳細ページへのリンク先一覧が完成します。

require 'open-uri'
require 'csv'

# スクレイピング先のURL
url = 'http://www.sample.jp/article/'
dir = []

filenames = Dir.open("article/",&:to_a) - [".", ".."]
filenames.each do |file|
  files = []
  files.push(url+file)
  dir.push(files)
end

# CSV出力と同時にターミナルにも内容を出力
test = CSV.open("article-urls.csv", "w") do |csv|
  dir.each do |row|
    csv << row
  end
end
puts test

吐き出したCSVデータを元に、本番サイトをスクレイピングしよう。

上のソースコードで吐き出したリンク先一覧のCSVを元に、
別のrbファイルで本番サイトをスクレイピングします。

require 'open-uri'
require 'nokogiri'
require 'kconv'
require 'csv'


line = []
ps = []
leadDt = []
articleLeadDescTitle = []
CSV.open("data-utf-8.csv", mode = "rt") do |csv|
  line = csv.readlines
end

line.each{ |link|
  for url in link do
    charset = nil
    html = open(url) do |f|
      charset = f.charset
      f.read
    end
   doc = Nokogiri::HTML.parse(html,nil,'utf-8')
   doc.xpath('//div[contains(@id,"mainColumn")]').each do |node|
     data = []
     articleTitle = node.css('h1').inner_text
     articleCatchCopy = node.css('h3').inner_text
     articleLeadTitle = node.css('p.leadComent').inner_text
     articleLeadText = node.css('p.lead').inner_text
      if !node.search('.//dl[contains(@class,"article01")]').nil?
          article01_inner = node.xpath('.//dl[contains(@class,"article01")]').inner_text
      end
      if !node.search('.//dl[contains(@class,"article02")]').nil?
          article02_inner = node.xpath('.//dl[contains(@class,"article02")]').inner_text
      end
      if !node.search('.//dl[contains(@class,"article03")]').nil?
          article03_inner = node.xpath('.//dl[contains(@class,"article03")]').inner_text
      end
     data.push(url)
     data.push(articleTitle.tosjis)
     data.push(articleCatchCopy.tosjis)
     data.push(articleLeadTitle.tosjis)
     data.push(articleLeadText.tosjis)
     data.push(article01_inner.tosjis)
     data.push(article02_inner.tosjis)
     data.push(article03_inner.tosjis)
     ps.push(data)
   end
  end
}

# CSV出力と同時にターミナルにも内容を出力
CSV.open("article-data.csv", "w") do |csv|
  ps.each do |row|
    csv << row
  end
end

ほとんどどこかのコピペだと思いますが、
大体こんな感じで全リンク先の特定のタグにある内容を取得出来ます。

スクレイピング時、リンク先一覧の中に本番のページが存在しないリンクが紛れている場合があります。
最初のスクレイピングはあくまで、ローカルにある全ファイル名に本番のリンクをくっつけただけなので、
吐き出した後、サクッとリンク先のページが存在しているかだけチェックしたほうが良いかもしれません。
たしか、存在しないとこは空の行が出来た気がします。

これがCSV化出来たら、重複した記事内容が無いか簡単に調べることも出来そうですね。

0
0
0

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
0
0