以前、ある案件で、
検索結果一覧にある全詳細ページの特定のタグ内にある内容が必要になったのですが、
その詳細ページに辿り着く方法が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化出来たら、重複した記事内容が無いか簡単に調べることも出来そうですね。