0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Ruby】anemoneとnokogiriでクローラーを作ってみた。

Last updated at Posted at 2020-11-12

システム開発にあたり、他のWEBページから情報を取得する必要があったので、クローラーを作成しました。

 最初に考えたこと

私がやろうとしていたことは、他のWEBページから情報を取得し、現在作成中のアプリのDBに保存することでした。ということで、なんとなく「情報を取得」ってことはスクレイピングか!という感じで意気込んでいました・・・。

 調査を開始し、分かったこと

自分がやろうとしていたことは、確かにスクレイピング。しかしながら、その情報を取得するためには、まずクローラーと呼ばれるものを作成しなければならないことが判明しました。

クローラーとは?

一方クローラーは、Webページ内にある全てのリンクを巡回して、深堀りしながら目的の情報を取得する方法です。この行為自体はクローリングと呼ばれます。
クローラーでリンクを探す際にはもちろんスクレイピングをしてHTMLのタグを解析して、リンク先を取得します。

スクレイピングとは?

スクレイピングとは、WebページのHTMLを解析してデータを抽出することです。

webdesign-3411373_640.jpg

要するに、
●スクレイピングは1つのページに情報が集まっている場合に使える。
●クローラーはWEBサイト内を巡回してくれる。

ということで、クローラーを作成し→その中にスクレイピングに関するコードを記述する→DBに保存する記述を書くという流れが見えてきました。

完成したソースコード

# ruby gemを使用 nokogiri anemoneを使えるようにした
require 'nokogiri'
require 'anemone'
require 'pry'
# 巡回起点となるURL
URL = 'https://********/********'.freeze

area_urls = []
prefecture_urls = []
city_urls = []
# サイト内を巡回する記述
Anemone.crawl(URL, depth_limit: 0, delay: 1) do |anemone|
  anemone.focus_crawl do |page|
    page.links.keep_if do |link|
      link.to_s.match(%r{*********/[0-9]{1,2}})
    end
    page.links.each do |link|
      area_urls << link
    end
  end
end

area_urls.each do |area|
  Anemone.crawl(area, depth_limit: 0, delay: 1) do |anemone|
    anemone.focus_crawl do |page|
      page.links.keep_if do |link|
        link.to_s.match(%r{**********/[0-9]{1,2}/[0-9]{5}})
      end
      page.links.each do |link|
        prefecture_urls << link
      end
    end
  end
end

prefecture_urls.each do |prefecture|
  Anemone.crawl(prefecture, depth_limit: 1, delay: 1, skip_query_strings: true) do |anemone|
    anemone.focus_crawl do |page|
      page.links.keep_if do |link|
        link.to_s.match(%r{**********/[0-9]{1,2}/[0-9]{5}/[0-9]})
      end
      page.links.each do |link|
        city_urls << link
      end
    end

    PATTERN = %r[**********/[0-9]{1,2}/[0-9]{5}/[0-9]].freeze

    anemone.on_pages_like(PATTERN) do |page|
      url = page.url.to_s

      str = url.to_s

      html = URI.parse(url).open
      # ここからスクレイピングの記述
      doc = Nokogiri::HTML.parse(html, nil, 'UTF-8')
# XpathでHTMLを指定
      name = doc.xpath('/html/body/div[4]/div/div[2]/div[1]/h1').text
      pos = doc.xpath('/html/body/div[4]/div/div[2]/table[1]/tbody/tr[3]/td/text()[1]').text
      post = pos.strip
      postcode = post.match(/[0-9]{7}/)
      add = doc.xpath('/html/body/div[4]/div/div[2]/table[1]/tbody/tr[3]/td/text()[2]').text
      address = add.strip
      tel = doc.xpath('/html/body/div[4]/div/div[2]/table[1]/tbody/tr[4]/td').text
      fax = doc.xpath('/html/body/div[4]/div/div[2]/table[1]/tbody/tr[5]/td').text
      staff_number = doc.xpath('/html/body/div[4]/div/div[2]/table[4]/tbody/tr[1]/td/p').text
      company = doc.xpath('/html/body/div[4]/div/div[2]/table[5]/tbody/tr[2]/td').text
      office_url = doc.xpath('/html/body/div[4]/div/div[2]/table[1]/tbody/tr[6]/td/a').text
      # 正規表現でURLから5桁の数字を抜き出す
      if str =~ %r{/(\d{5})(/|$)}
        city_number = Regexp.last_match(1)
        p Regexp.last_match(1)
      end
# インスタンスを作成し、スクレイピングで取得した情報をDBに保存、その際にバリデーションを無視する。
      offices = Office.new(name: name,
                           postcode: postcode,
                           tel: tel,
                           fax: fax,
                           address: address,
                           staff_number: staff_number,
                           company: company,
                           url: office_url,
                           city_number: city_number)
      offices.save(validate: false)
    end
  end
end


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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?