【Ruby + Nokogiri】로 yahoo 뉴스를 스크래핑 → CSV 보존

이전에 Python의 BeautifulSoup을 사용하여 스크래핑을 한 적이 있었지만 Ruby에서도 Nokogiri라는 라이브러리로 실현할 수 있다는 것으로 시도했습니다.

먼저 완성 코드, 완성품에서

scraping.rb

require 'nokogiri'
require 'open-uri'
require "csv"

require "byebug"


url_base = "https://news.yahoo.co.jp/"

def get_categories(url)
  html = open(url)
  doc = Nokogiri::HTML.parse(html)
  categories = doc.css(".yjnHeader_sub_cat li a")
  categories.map do |category|
    cat_name = category.text
    cat = category[:href]
  end
end

@cat_list = get_categories(url_base)
@infos = []


@cat_list.each do |cat|
  url = "#{url_base + cat}"
  html = open(url)
  doc = Nokogiri::HTML.parse(html)
  titles = doc.css(".topicsListItem a")
  i = 1
  titles.each do |title|
    @infos << [i,title.text]
    i += 1
  end
end

CSV.open("result.csv", "w") do |csv|
  @infos.each do |info|
    csv << info
    puts "-------------------------------"
    puts info
  end
end




각각 해설해 갑니다.

파일 로드


require 'nokogiri'
require 'open-uri'
require "csv"

require "byebug"


이번에 사용하는 것은 Nokogiri와 open-uri, 그리고 CSV 저장을위한 CSV입니다.

Nokogiri는 HTML과 XML 코드를 구문 분석하고 선택기로 추출하는 Ruby 라이브러리입니다. 셀렉터는 css 외에 xpath에서도 지정할 수 있으므로 복잡한 구조를 한 페이지에서도 스크래핑을 원활하게 할 수 있습니다.

스크래핑 대상 페이지 구조






이번에는 각 주제의 제목을 취득해 가서 최종적으로 CSV 파일에 정리합니다.

주제의 페이지는 yjnHeader_sub라는 클래스의 li 안에 있는 링크(a 태그)로부터 연결되어 있는 것 같습니다.

카테고리별 링크 가져오기


url_base = "https://news.yahoo.co.jp/"

def get_categories(url)
  html = open(url)
  #parseで読み込んだURLのHTMLコードを取得
  doc = Nokogiri::HTML.parse(html)
  #cssセレクターを使い、先ほどのカテゴリーに繋がっているaタグをすべて取得
  categories = doc.css(".yjnHeader_sub_cat li a")
  categories.map do |category|
    #取得したaタグからhrefの中身(リンク先のURL)をひとつづつ取り出して返します
    cat = category[:href]
  end
end

#@cat_listとして取得したリンクをまとめておきます
@cat_list = get_categories(url_base)

주제 제목 얻기



방금 검색한 링크를 사용하여 주제별 제목을 검색합니다.

@infos = []

@cat_list.each do |cat|
 #トピックページのURLは元のURL + 取得したURLのため
  url = "#{url_base + cat}"
  html = open(url)
  doc = Nokogiri::HTML.parse(html)
  titles = doc.css(".topicsListItem a")
  i = 1
  titles.each do |title|
  #CSVにまとめるためにトピックのナンバーとタイトルをセットで格納します
    @infos << [i,title.text]
    i += 1
  end
end

획득한 타이틀을 CSV로 정리



마지막으로 정리한 제목을 CSV에 저장합니다.

#CSVライブラリを使い"result.csv"を新規作成
CSV.open("result.csv", "w") do |csv|
  @infos.each do |info|
  #csvに追加するとともにログとして使いした項目を出力しています。
    csv << info
    puts "-------------------------------"
    puts info
  end
end



편지 대책



그러나 이대로는 아마 문자 깨져 버리기 때문에 BOM을 붙여 다시 저장합니다.
(본래라면 CSV 보존중에 하는 것이 맞습니다만, 능숙하지 못했기 때문에 일단 이쪽에서 대응했습니다)

메모장에서 "result.csv"를 열고 덮어쓰기 저장을 선택합니다.





이 때 UTF-8 (BOM 포함)을 선택하고 다시 저장하십시오.



다시 csv를 열면 깨짐이 제거됩니다.

마지막으로



아직 이르지 않는 점이 많다고 생각하기 때문에 지적이 있으면 코멘트 받을 수 있으면 다행입니다.

좋은 웹페이지 즐겨찾기