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!