12/08/2018, 13:53

Xây dựng web crawler bằng rails

//WIP: Bài viết chưa hoàn thiện Trong thời đại phát triển của công nghệ thông tin, nguồn dữ liệu trên internet là vô cùng phong phú và để phục vụ cho nhu cầu cá nhân cũng như một sản phẩm nào đó thì việc khai thác được lượng thông tin không giới hạn này sẽ rất có ích cho chúng ta. Ví dụ bạn ...

//WIP: Bài viết chưa hoàn thiện

Trong thời đại phát triển của công nghệ thông tin, nguồn dữ liệu trên internet là vô cùng phong phú và để phục vụ cho nhu cầu cá nhân cũng như một sản phẩm nào đó thì việc khai thác được lượng thông tin không giới hạn này sẽ rất có ích cho chúng ta.

Ví dụ bạn đang cần tạo một trang web tin tức và muốn lấy bài từ các trang báo khác (một cách dễ dàng) hoặc đang cần một lượng dữ liệu lớn cho nhu cầu khai phá hoặc xử lý ngôn ngữ tự nhiên, việc xây dựng một crawler để lấy dữ liệu là việc vô cùng cần thiết.

Trong bài viết này, mình sẽ hướng dẫn các bạn tạo một crawler hết sức cơ bản bằng rails với sự hỗ trợ của gem nokogiri cho website tinhte.vn.

Tạo project mới

rails new tinhte_crawler

Thêm gem nokogiri vào Gemfile

gem "nokogiri"

Cài đặt gem

bundle install

Tạo model và controller cho các bài viết và migrate database

rails g model Article title:string content:text
rails g controller Articles new create index
rails db:migrate

Crawl dữ liệu bằng nokogiri với model vừa tạo

app/models/article.rb

class Article < ApplicationRecord
  #config URL cho crawler
  BASE_TINHTE_URL = "https://tinhte.vn"
  LIST_URL = "https://tinhte.vn/?wpage="
  class << self
   #hàm crawl dữ liệu theo số trang yêu cầu
   def crawl_article number_of_page
   hrefs = []
   1.upto(number_of_page) do |x|
     url = LIST_URL + x.to_s
     page = Nokogiri::HTML(open(url))
     doc = page.css(".subHeading")
     hrefs = hrefs + doc.css("a").map {|a|
       a["href"]
     }.compact.uniq
   end
   hrefs.each do |href|
     remote_url = BASE_TINHTE_URL + href
     begin
       #Get dữ liệu bằng Nokogiri
       tinhte_content = Nokogiri::HTML(open(remote_url))
       #lấy title của bài viết bằng cách tìm thành phần css có class là title và convert về dạng text
       title = tinhte_content.css("title").first.text
       #lấy content của bài viết bằng cách xác định class css
       content = tinhte_content.css(".uix_discussionAuthor .baseHtml").text
       #tạo một article mới
       Article.create! title: title, content: content
       ensure
       #tạo thời gian nghỉ cho các request để tránh bị coi là tấn công ddos
       sleep 1.0 + rand
     end
   end
  end

Tạo routes cho các trang article

config/routes.rb

Rails.application.routes.draw do
  resources :articles
end

Tạo controller và views cho các bài viết

TODO

Test lại bằng rails controller

rails c
Article.crawl_article 4 (crawl 4 trang đầu của tinhte.vn)
Article.all

Bài viết còn sơ sài, mình sẽ cố gắng bổ sung thêm trong thời gian sắp tới, mọi ý kiến và câu hỏi các bạn có thể để lại comment ở phần dưới, xin cảm ơn!

0