Chuyện của dev's blog

Làm sao để lấy thông tin tất cả các công ty trên itviec.com trong 30 phút

 11/03/2018  2819

Bài viết này mình lấy web itviec.com làm ví dụ vì trước mình cần lấy danh sách các công ty từ trang web này để các bạn có nơi bày tỏ tâm sự của mình :)

Để đáp ứng nhu cầu của mình thì phải làm 2 việc:

  • Lấy ra được hết các URL của các công ty
  • Sau đó request đến từng URL để lấy ra các thông tin cần thiết như: logo, tên, địa điểm...

2 cách lấy ra danh sách URL của các công ty

Vào trang "Việc làm IT theo công ty"

Trang này các bạn có thể thấy ngay bên dưới Footer của itviec https://itviec.com/viec-lam-it-theo-ten-cong-ty
Đây là trang liệt kê ra tất cả các công ty sắp xếp theo bảng chữ cái từ A-Z.

Từ đây các bạn có thể mở "Console log" viết script hay dùng các "Chrome extension" để trích xuất ra được các link của các công ty :)

Thường cách website lớn sẽ sử dụng "Sitemap" để khai báo giúp cho các công cụ tìm kiếm hiểu rõ hơn về website đó.
Cho nên khi các bạn viết Crawler thì có khi chỉ cần truy cập vào sitemap sẽ giúp công việc của bạn đơn giản hơn rất nhiều :)

Đối với itviec.com thì link Sitemaphttps://itviec.com/sitemap.xml
Khi bạn mở bằng trình duyệt thì bạn sẽ thấy có đoạn XML như sau:

<sitemap>
<loc>https://itviec.com/homepage.xml</loc>
<lastmod>2018-03-09T10:40:18+07:00</lastmod>
</sitemap>
<sitemap>
<loc>https://itviec.com/companies_en.xml</loc>
<lastmod>2018-03-09T10:40:18+07:00</lastmod>
</sitemap>
<sitemap>
<loc>https://itviec.com/companies_review_en.xml</loc>
<lastmod>2018-03-09T10:40:20+07:00</lastmod>
</sitemap>
<sitemap>
<loc>https://itviec.com/companies_vn.xml</loc>
<lastmod>2018-03-09T10:40:22+07:00</lastmod>
</sitemap>

Nhìn vào đoạn trên mình thì mình biết ngay danh sách các công ty nằm ở 2 URL: https://itviec.com/companies_en.xmlhttps://itviec.com/companies_vn.xml
Vì mình muốn lấy thông tin bằng tiếng việt cho nên mình chọn link thứ 2! Thử mở link thứ 2 bằng trình duyệt, bạn sẽ thấy nhiều dòng như sau:

<url>
<loc>
https://itviec.com/nha-tuyen-dung/vietnam-cloud-services
</loc>
<lastmod>2018-03-09T10:40:20+07:00</lastmod>
<changefreq>weekly</changefreq>
<priority>0.6</priority>
</url>
<url>
<loc>https://itviec.com/nha-tuyen-dung/shinhan-bank</loc>
<lastmod>2018-03-09T10:40:20+07:00</lastmod>
<changefreq>weekly</changefreq>
<priority>0.6</priority>
</url>

Như vậy từ đây bạn có thể biết script để lấy ra hết danh sách URL của các công ty từ file Sitemap này. Vì mình làm biếng nên mình dùng dịch vụ online của web này https://robhammond.co/tools/xml-extract

Lấy thông tin của từng công ty

Sau khi mình đã trích xuất ra tất cả các URL thì mình lưu lại trong 1 file text. Và công việc bây giờ rất đơn giản:
Đọc file text chứa các URL lên, request đến từng URL lấy ra được HTML và dùng các thư viện xử lý DOM để trích xuất ra các thông tin cần thiết :)

Đây là đoạn code mình viết trên NodeJs cho các bạn tham khảo:

const Crawler = require('crawler');
const Promise = require('bluebird');
const Readline = require('readline');
const fs = require('fs');

require('total.js').load('release', ['definitions', 'models']);

F.on('load', function() {
  const file = './urls.csv';
  const lineReader = Readline.createInterface({
    input: fs.createReadStream(file)
  });
  let urls = [];

  const c = new Crawler({
    rateLimit: 1000,
    maxConnections : 1,
    userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.109 Safari/537.36',
    callback : function (error, res, done) {
      if (error){
        console.log(error);
        done();
      } else{
        let $ = res.$;
        let name = $(".name-and-info h1").text().trim();
        let slug = $("link[rel=canonical]").attr('href').replace('https://itviec.com/nha-tuyen-dung/', '').trim();
        let logo = $('.logo-container img').attr('src');
        let location = $('.name-and-info .fa-map-marker').parent().text().trim().split("\n")[0].trim();
        let type = $('.company-info .gear-icon').text().trim();
        let size = $('.company-info .group-icon').text().trim();
        let country = $('.company-info .country .name').text().trim();
        let time = $('.name-and-info .working-date span').text().trim();

        let info = {
          slug: slug,
          name: name,
          logo: logo,
          location: location,
          type: type,
          size: size,
          country: country,
          time: time
        };

        if (!name || !logo || !location) {
          return done();
        }

        let company = MODEL('company').create();

        company.name = name;
        company.slug = slug;
        company.location = location;
        company.country = country;

        DATABASE()
          .collection('companies')
          .insert(company)
          .then(function() {
            console.log(`Inserted "${name}"`);
            done();
          })
          .catch(function(err) {
            console.log(err);
            done();
          });
      }
    }
  });

  lineReader.on('line', function (line) {
    let url = line.trim();
    urls.push(url);
  });

  lineReader.on('close', function () {
    Promise.each(urls, function (url) {
      let slug = url.replace('https://itviec.com/nha-tuyen-dung/', '').trim();

      return DATABASE()
        .collection('companies')
        .findOne({
          slug: slug
        })
        .then(function(res) {
          if (res) return false;

          c.queue(url);
        });
    });
  });
});

Lời kết

Như các bạn đã thấy đối với các website không "Open" cho lắm thì đầu tiên cứ tìm Sitemap của nó trước xem sao. Nếu có thì sẽ tiết kiệm thời gian của mình rất là nhiều :)
Các bạn có thắc mắc gì cứ comment bên dưới nhé. Have fun at #chuyencuadev.