created sample rake task for crawler
From Task/6_create_crawler into master
-
-
added 1 commit
- e16f8904 - fix description, requirement from array to string, crawler first page on CareerBuilder
Toggle commit list -
-
lib/tasks/web_crawler.rake 0 → 100644
1 require 'open-uri' 2 require 'csv' 3 require 'zip' 4 5 namespace :job do -
Master
namespace thường chỉ vào những cái nào cụ thể, như là 1 đối tượng hoặc là 1 cái gì đó chung cho các task. Em tham khảo ở đây sẽ thấy rails đặt tên namespace cho rake task nè
https://guides.rubyonrails.org/command_line.html
ví dụ:
rails db:migrate rails db:migrate:down rails db:migrate:redo rails db:migrate:status rails db:migrate:upnên chỗ này em hãy đổi lại thành
namespace :crawler -
-
-
lib/tasks/web_crawler.rake 0 → 100644
1 require 'open-uri' 2 require 'csv' 3 require 'zip' 4 5 namespace :job do 6 desc 'importjob' 7 8 task web_job_crawler: :environment do -
Master
tương tự comment ở trên thì chỗ này em đổi lại thành
task jobs: :environmentvà tương tự với industries, cities bên dưới thì em sẽ có commands làrails crawler:jobs rails crawler:industries rails crawler:cities -
-
-
lib/tasks/web_crawler.rake 0 → 100644
1 require 'open-uri' 2 require 'csv' 3 require 'zip' 4 5 namespace :job do 6 desc 'importjob' 7 8 task web_job_crawler: :environment do 9 parsed_page ||= Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/viec-lam/tat-ca-viec-lam-vi.html').body) -
Master
chỗ này em đâu cần phải dùng
||=. Em tìm lại định nghĩa của operator này nha, tại sao và khi nào dùng nó.chỗ này em chỉ cần
=là được -
-
-
lib/tasks/web_crawler.rake 0 → 100644
1 require 'open-uri' 2 require 'csv' 3 require 'zip' 4 5 namespace :job do 6 desc 'importjob' 7 8 task web_job_crawler: :environment do 9 parsed_page ||= Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/viec-lam/tat-ca-viec-lam-vi.html').body) 10 job_item = parsed_page.css('div.job-item') -
Master
job_itemlà 1 array có nhiều phần tử thì em đặt với số nhiều nha =>jobs -
MasterEdited by phuctmZigexn
job_item = parsed_page.css('div.job-item')chỗ này em đang muốn lấy ra các jobs thì thay vì em lấy cái
div.job-itemrồi em lại phải đi lấy từng link để đi vào trang job detail thì em nên lấy trực tiếp luôn cáijob_linknhư vậy phải nhanh và tiện hơn không?=>
parsed_page.css('.job-item .job_link') -
-
-
lib/tasks/web_crawler.rake 0 → 100644
1 require 'open-uri' 2 require 'csv' 3 require 'zip' 4 5 namespace :job do 6 desc 'importjob' 7 8 task web_job_crawler: :environment do 9 parsed_page ||= Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/viec-lam/tat-ca-viec-lam-vi.html').body) 10 job_item = parsed_page.css('div.job-item') 11 (0..job_item.count - 1).each do |item| -
Master
đối với ruby
job_item.countthì em hãy dùnglengthref: https://github.com/JuanitoFatas/fast-ruby#arraylength-vs-arraysize-vs-arraycount-code
-
-
-
lib/tasks/web_crawler.rake 0 → 100644
1 require 'open-uri' 2 require 'csv' 3 require 'zip' 4 5 namespace :job do 6 desc 'importjob' 7 8 task web_job_crawler: :environment do 9 parsed_page ||= Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/viec-lam/tat-ca-viec-lam-vi.html').body) 10 job_item = parsed_page.css('div.job-item') 11 (0..job_item.count - 1).each do |item| 12 job_link = job_item[item].css('div.title a').attribute('href').text 13 unparsed_job_link = HTTParty.get(job_link) 14 parsed_job_link ||= Nokogiri::HTML(unparsed_job_link.body) -
Master
unparsed_job_link = HTTParty.get(job_link) parsed_job_link ||= Nokogiri::HTML(unparsed_job_link.body)2 dòng này em gộp lại được như cách em làm ở trên mà đặt tên biến là
job_pagenhé hoặc tên nào em thấy hợp lí -
-
-
-
lib/tasks/web_crawler.rake 0 → 100644
1 require 'open-uri' 2 require 'csv' 3 require 'zip' 4 5 namespace :crawler do 6 desc 'importjob' 7 8 task jobs: :environment do 9 parsed_page = Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/viec-lam/tat-ca-viec-lam-vi.html').body) 10 jobs_item = parsed_page.css('div.job-item .job_link') -
Master
jobs_item = parsed_page.css('div.job-item .job_link') (0..jobs_item.length - 1).each do |item|giữa 2 chỗ này mình enter break line 1 dòng đi em, mỗi 1 phần mình break line ra cho dễ nhìn
-
-
-
lib/tasks/web_crawler.rake 0 → 100644
1 require 'open-uri' 2 require 'csv' 3 require 'zip' 4 5 namespace :crawler do 6 desc 'importjob' 7 8 task jobs: :environment do 9 parsed_page = Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/viec-lam/tat-ca-viec-lam-vi.html').body) 10 jobs_item = parsed_page.css('div.job-item .job_link') 11 (0..jobs_item.length - 1).each do |item| -
Master
(0..jobs_item.length - 1).each do |item|chỗ này em để là
jobs_item.each do |item|được mà ??? Xem lại cách duyệt array trong ruby nha -
-
-
lib/tasks/web_crawler.rake 0 → 100644
1 require 'open-uri' 2 require 'csv' 3 require 'zip' 4 5 namespace :crawler do 6 desc 'importjob' 7 8 task jobs: :environment do 9 parsed_page = Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/viec-lam/tat-ca-viec-lam-vi.html').body) 10 jobs_item = parsed_page.css('div.job-item .job_link') 11 (0..jobs_item.length - 1).each do |item| 12 job_link = jobs_item[item].attribute('href').text -
Master
job_link = jobs_item[item].attribute('href').text job_page = Nokogiri::HTML(HTTParty.get(job_link).body)theo comment duyệt array ở trên thì em sửa lại chỗ
job_linknha. Đối với những biến nào chỉ sử dụng có 1 lần, ví dụ như job_link thì nếu dòng code không quá dài (>100 kí tự) thì em gom vào 1 dòng luôn. anh ví dụ=>
job_page = Nokogiri::HTML(HTTParty.get(item.attribute('href').text).body) -
-
-
lib/tasks/web_crawler.rake 0 → 100644
2 require 'csv' 3 require 'zip' 4 5 namespace :crawler do 6 desc 'importjob' 7 8 task jobs: :environment do 9 parsed_page = Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/viec-lam/tat-ca-viec-lam-vi.html').body) 10 jobs_item = parsed_page.css('div.job-item .job_link') 11 (0..jobs_item.length - 1).each do |item| 12 job_link = jobs_item[item].attribute('href').text 13 job_page = Nokogiri::HTML(HTTParty.get(job_link).body) 14 job_desc = job_page.css('div.job-desc') 15 job_detail = job_page.css('section.job-detail-content') 16 # title - company 17 title = job_desc.css('h1.title').text -
Master
thay vì em phải lấy
job_descrồi mới lấyjob_titlethì sao không lấy thẳng title luôn???job_descđâu có tác dụng gì đâu?job_title = job_page.css('div.job-desc .title').texttận dụng hết khả năng của CSS selector và XML để lấy đúng giá trị cần thiết luôn nha. Nokogiri làm được hết đó.
-
-
-
-
added 1 commit
- 2b3e5d23 - add argument to crawl 5 or all page ,merge branch migration, import data to City and Industry
Toggle commit list -
-
-
added 3 commits
-
9a32f409...ca4035a9 - 2 commits from branch
master - f5f71e9f - Merge branch 'master' into 'Task/6_create_crawler'
Toggle commit list -
9a32f409...ca4035a9 - 2 commits from branch
-
-
57 57 # Windows does not include zoneinfo files, so bundle the tzinfo-data gem 58 58 gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] 59 59 gem 'slim-rails', '~> 3.2' 60 gem 'nokogiri', '~> 1.11', '>= 1.11.7' 61 gem 'httparty', '~> 0.18.1' 62 gem 'rubocop-rails', '~> 2.11', '>= 2.11.3' -
lib/tasks/web_crawler.rake 0 → 100644
1 require 'open-uri' 2 require 'csv' -
lib/tasks/web_crawler.rake 0 → 100644
1 require 'open-uri' 2 require 'csv' 3 require 'zip' 4 5 namespace :crawler do 6 desc 'crawler from CareerBuilder' 7 task jobs: :environment do 8 ARGV.each { |a| task a.to_sym { ; } } -
Master
dạ vì nếu sử dụng cách này. vd ta chạy
rake add 1 2rails sẽ chạy: $ rake 1 $ rake 2 vì 1 và 2 không phải task, ta sẽ gặp lỗi trừ khi ta viết task rỗng cho nó -
-
-
-
-
lib/tasks/web_crawler.rake 0 → 100644
104 105 desc 'crawler industry form CareerBuilder' 106 task industries: :environment do 107 parsed_page = Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/tim-viec-lam.html').body) 108 list_job = parsed_page.css('div.list-of-working-positions ul.list-jobs li a') 109 list_job.each do |part| 110 industry = part.text.squish.strip 111 Industry.find_or_create_by(name: industry) 112 end 113 end 114 115 desc 'crawler city form CareerBuilder' 116 task cities: :environment do 117 parsed_page ||= Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/tim-viec-lam.html').body) 118 list_location = parsed_page.css('div.main-jobs-by-location ul li') 119 list_location.each do |part| -
lib/tasks/web_crawler.rake 0 → 100644
106 task industries: :environment do 107 parsed_page = Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/tim-viec-lam.html').body) 108 list_job = parsed_page.css('div.list-of-working-positions ul.list-jobs li a') 109 list_job.each do |part| 110 industry = part.text.squish.strip 111 Industry.find_or_create_by(name: industry) 112 end 113 end 114 115 desc 'crawler city form CareerBuilder' 116 task cities: :environment do 117 parsed_page ||= Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/tim-viec-lam.html').body) 118 list_location = parsed_page.css('div.main-jobs-by-location ul li') 119 list_location.each do |part| 120 city_name = part.text 121 region = 1 -
Master
-
-
-
lib/tasks/web_crawler.rake 0 → 100644
107 parsed_page = Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/tim-viec-lam.html').body) 108 list_job = parsed_page.css('div.list-of-working-positions ul.list-jobs li a') 109 list_job.each do |part| 110 industry = part.text.squish.strip 111 Industry.find_or_create_by(name: industry) 112 end 113 end 114 115 desc 'crawler city form CareerBuilder' 116 task cities: :environment do 117 parsed_page ||= Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/tim-viec-lam.html').body) 118 list_location = parsed_page.css('div.main-jobs-by-location ul li') 119 list_location.each do |part| 120 city_name = part.text 121 region = 1 122 if city_name.include?(key = 'Việc làm tại') -
lib/tasks/web_crawler.rake 0 → 100644
116 task cities: :environment do 117 parsed_page ||= Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/tim-viec-lam.html').body) 118 list_location = parsed_page.css('div.main-jobs-by-location ul li') 119 list_location.each do |part| 120 city_name = part.text 121 region = 1 122 if city_name.include?(key = 'Việc làm tại') 123 city_name = city_name.remove(key).strip 124 region = 0 125 end 126 city = { 127 name: city_name, 128 region: region 129 } 130 City.create( 131 name: city[:name], -
lib/tasks/web_crawler.rake 0 → 100644
71 company_object = Company.find_or_create_by(name: company_name) 72 job_object = Job.create({ title: job_title, 73 job_type: job_type, 74 salary: salary, 75 experience: experience, 76 position: level, 77 expiration_date: expiration_date, 78 description: description, 79 benefit: benefits, 80 requirement: requirement, 81 other_info: other_info, 82 company_id: company_object.id, 83 created_at: update_at, 84 updated_at: update_at }) 85 industries.map do |industry| 86 industry_objects = Industry.find_or_create_by(name: industry) -
lib/tasks/web_crawler.rake 0 → 100644
72 job_object = Job.create({ title: job_title, 73 job_type: job_type, 74 salary: salary, 75 experience: experience, 76 position: level, 77 expiration_date: expiration_date, 78 description: description, 79 benefit: benefits, 80 requirement: requirement, 81 other_info: other_info, 82 company_id: company_object.id, 83 created_at: update_at, 84 updated_at: update_at }) 85 industries.map do |industry| 86 industry_objects = Industry.find_or_create_by(name: industry) 87 job_object.industries << industry_objects -
lib/tasks/web_crawler.rake 0 → 100644
68 company_name = job_page.css('div.job-desc a.job-company-name').text 69 # Cities 70 cities = job_page.css('.job-detail-content .detail-box .map p a').map(&:text) 71 company_object = Company.find_or_create_by(name: company_name) 72 job_object = Job.create({ title: job_title, 73 job_type: job_type, 74 salary: salary, 75 experience: experience, 76 position: level, 77 expiration_date: expiration_date, 78 description: description, 79 benefit: benefits, 80 requirement: requirement, 81 other_info: other_info, 82 company_id: company_object.id, 83 created_at: update_at, -
lib/tasks/web_crawler.rake 0 → 100644
16 end 17 (1..total_pages).each do |page| 18 parsed_page = Nokogiri::HTML(HTTParty.get("https://careerbuilder.vn/viec-lam/tat-ca-viec-lam-trang-#{page}-vi.html").body) 19 jobs_item = parsed_page.css('div.job-item .job_link') 20 jobs_item.each do |item| 21 retries ||= 0 22 url ||= item.attribute('href').text 23 job_page = Nokogiri::HTML(HTTParty.get(url).body) 24 # Job 25 job_title = job_page.css('div.job-desc h1.title').text 26 # update_at, job_industries, job_type, salary, experience, level, expiration_date 27 detail_box_items = job_page.css('.job-detail-content .detail-box ul li') 28 # init 29 update_at, job_type, salary, experience, level, expiration_date = '' 30 industries = [] 31 detail_box_items.each do |info_item| -
Master
phần này anh thấy em làm tương tự cách bên dưới lấy data của
benefits, description, requirement, other_infothì dễ nhìn hơn đó Hà -
Master
code mẫu cho em
detail_box_items.each do |info_item| key = info_item.css('strong').text.strip default_value = info_item.css('p').text.squish case key when 'Ngày cập nhật' update_at = default_value.to_time when 'Ngành nghề' industries = default_value.split(' , ') when 'Hình thức' job_type = default_value when 'Lương' salary = default_value when 'Kinh nghiệm' experience = default_value.squish when 'Cấp bậc' level = default_value when 'Hết hạn nộp' expiration_date = default_value.to_time end end
-
-
-
lib/tasks/web_crawler.rake 0 → 100644
37 when info.include?(key = 'Ngành nghề') 38 industries = info.squish.remove(key).strip.split(' , ') 39 when info.include?(key = 'Hình thức') 40 job_type = info.squish.remove(key).strip 41 when info.include?(key = 'Lương') 42 salary = info.squish.remove(key).strip 43 when info.include?(key = 'Kinh nghiệm') 44 experience = info.squish.remove(key).strip 45 when info.include?(key = 'Cấp bậc') 46 level = info.squish.remove(key).strip 47 when info.include?(key = 'Hết hạn nộp') 48 expiration_date = info.squish.remove(key).strip.to_time 49 end 50 end 51 # benefits, description, requirement, other_info 52 job_detail_rows = job_page.css('section.job-detail-content div.detail-row') -
Master
phần lấy data này cần refactor lại nha. anh thấy dòng xử lý này áp dụng được cho cả 4 fields luôn
detail_row.css(':not(h3.detail-title)').map(&:text).map(&:squish)[1..-1].reject(&:blank?).join('---')Don't Repeat Yourself
-
-
lib/tasks/web_crawler.rake 0 → 100644
96 end 97 end 98 99 desc 'crawler industry form CareerBuilder' 100 task industries: :environment do 101 parsed_page = Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/tim-viec-lam.html').body) 102 list_job = parsed_page.css('div.list-of-working-positions ul.list-jobs li a') 103 list_job.each do |part| 104 industry = part.text.squish.strip 105 Industry.find_or_create_by(name: industry) 106 end 107 end 108 109 desc 'crawler city form CareerBuilder' 110 task cities: :environment do 111 parsed_page ||= Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/tim-viec-lam.html').body) -
Master
vì sử dụng recuse nên dùng toán tử
||=đó anh ơi -
-
lib/tasks/web_crawler.rake 0 → 100644
100 task industries: :environment do 101 parsed_page = Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/tim-viec-lam.html').body) 102 list_job = parsed_page.css('div.list-of-working-positions ul.list-jobs li a') 103 list_job.each do |part| 104 industry = part.text.squish.strip 105 Industry.find_or_create_by(name: industry) 106 end 107 end 108 109 desc 'crawler city form CareerBuilder' 110 task cities: :environment do 111 parsed_page ||= Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/tim-viec-lam.html').body) 112 list_location = parsed_page.css('div.main-jobs-by-location ul li') 113 list_location.each do |city| 114 city_name = city.text 115 region = City.regions[:international] -
lib/tasks/web_crawler.rake 0 → 100644
105 Industry.find_or_create_by(name: industry) 106 end 107 end 108 109 desc 'crawler city form CareerBuilder' 110 task cities: :environment do 111 parsed_page ||= Nokogiri::HTML(HTTParty.get('https://careerbuilder.vn/tim-viec-lam.html').body) 112 list_location = parsed_page.css('div.main-jobs-by-location ul li') 113 list_location.each do |city| 114 city_name = city.text 115 region = City.regions[:international] 116 if city_name.include?('Việc làm tại') 117 city_name = city_name.remove('Việc làm tại').strip 118 region = City.regions[:vietnam] 119 end 120 City.create( -
lib/tasks/web_crawler.rake 0 → 100644
57 when 'Phúc lợi' 58 benefits = detail_row.css(':not(h3.detail-title)').map(&:text).map(&:squish)[1..-1].reject(&:blank?).join('---') 59 when 'Mô tả Công việc' 60 description = detail_row.css(':not(h3.detail-title)').map(&:text).map(&:squish)[1..-1].reject(&:blank?).join('---') 61 when 'Yêu Cầu Công Việc' 62 requirement = detail_row.css(':not(h3.detail-title)').map(&:text).map(&:squish)[1..-1].reject(&:blank?).join('---') 63 when 'Thông tin khác' 64 other_info = detail_row.css(':not(h3.detail-title)').map(&:text).map(&:squish)[1..-1].reject(&:blank?).join('---') 65 end 66 end 67 # Company 68 company_name = job_page.css('div.job-desc a.job-company-name').text 69 # Cities 70 cities = job_page.css('.job-detail-content .detail-box .map p a').map(&:text) 71 company_object = Company.find_or_create_by(name: company_name) 72 job_object = Job.create({ title: job_title, -
lib/tasks/web_crawler.rake 0 → 100644
55 detail_title = detail_row.css('.detail-title').text.strip 56 case detail_title 57 when 'Phúc lợi' 58 benefits = detail_row.css(':not(h3.detail-title)').map(&:text).map(&:squish)[1..-1].reject(&:blank?).join('---') 59 when 'Mô tả Công việc' 60 description = detail_row.css(':not(h3.detail-title)').map(&:text).map(&:squish)[1..-1].reject(&:blank?).join('---') 61 when 'Yêu Cầu Công Việc' 62 requirement = detail_row.css(':not(h3.detail-title)').map(&:text).map(&:squish)[1..-1].reject(&:blank?).join('---') 63 when 'Thông tin khác' 64 other_info = detail_row.css(':not(h3.detail-title)').map(&:text).map(&:squish)[1..-1].reject(&:blank?).join('---') 65 end 66 end 67 # Company 68 company_name = job_page.css('div.job-desc a.job-company-name').text 69 # Cities 70 cities = job_page.css('.job-detail-content .detail-box .map p a').map(&:text) -
lib/tasks/web_crawler.rake 0 → 100644
38 industries = info.squish.remove(key).strip.split(' , ') 39 when info.include?(key = 'Hình thức') 40 job_type = info.squish.remove(key).strip 41 when info.include?(key = 'Lương') 42 salary = info.squish.remove(key).strip 43 when info.include?(key = 'Kinh nghiệm') 44 experience = info.squish.remove(key).strip 45 when info.include?(key = 'Cấp bậc') 46 level = info.squish.remove(key).strip 47 when info.include?(key = 'Hết hạn nộp') 48 expiration_date = info.squish.remove(key).strip.to_time 49 end 50 end 51 # benefits, description, requirement, other_info 52 job_detail_rows = job_page.css('section.job-detail-content div.detail-row') 53 benefits, description, requirement, other_info = [] -
Master
benefits, description, requirement, other_infotrong DB em để 4 cột này ở dạngtextthì sao ở đây em để là[], lúc join vào là thành string rồi mà=> lưu vào DB thì value của 4 cột này có đúng ko?
-
Master
mà anh thấy data lấy về của 4 cột này có vẻ sai sai :)))
-
-
-
-
-
-
Toggle commit list
-
Toggle commit list
-
merged
Toggle commit list