Thứ Bảy, 9 tháng 5, 2020

Master về con trỏ this - cách khắc phục các lỗi thường gặp


Trong blog lần này mình sẽ chia sẽ tổng quan về con trỏ this , và một số lỗi thường gặp , các câu hỏi này rất rất hay xuất hiện trong các buổi interview và nó nằm trong các vấn đề nâng cao của javascript

 This đối với những bạn mới học thì có vẻ nó khá đơn giản , vì các bạn chỉ nghĩ đơn giản là nó sẽ refer đến object chứa nó ,  đúng nhưng chưa đủ ,  vì có lẽ các bạn chưa gặp qua nhiều vấn đề chuyên sâu về this

Tổng quan this keyword

Như trên , thì cơ bản this là refer(tham chiếu) đến object chứa nó , nhớ nhé : LÀ OBJECT CHỨA NÓ để tí nữa mình còn nhắc lại , đối với các newbie thì sẽ hiểu như thế này

Thái là con trai nhưng anh ấy thích trai
Thắng là con trai nhưng anh ấy lại thích ngắm trai 6 múi

 ở ví dụ trên , thì Thái và Thắng là một đối tượng , và anh ấy là đại từ nhân xưng thay thế cho Thái và Thắng => this =  anh ấy , và object =  Thái và Thắng

Ví dụ:

var user = {
    name : "Vo Minh Tan",
    age : 19,
 
    getName : function(){
        return this.name;
    },
    getAge : function(){
        return this.age;
    }
}
console.log(user.getName());   // Vo Minh Tan
console.log(user.getAge()); //19

Như ví trụ trên thì this thay thế có object chưa nó cụ thể là user , thay vì gọi user.name thì dùng this.nameBasic là thế , sau đây là một số lưu ý khi dùng this , mình hay gọi là 5 rules of THIS :

  • Trong một phương thức, this được refer đến chính đối tượng chứa nó
  • Nếu đứng một mình this refer đến Global Object ( Window )
  • Trong một hàm this refer đến Global Object ( Window )
  • Trong một hàm ( strict mode ) this không được định nghĩa
  • Trong một sự kiện, this được refer đến chính element nhận sự kiện đó

Note : Đối tượng Window là container chính của toàn bộ code JavaScript của trang Web , check trong chrome dev tool để hiểu rõ hơn

Ví dụ :

1.  Trong một phương thức, this được refer đến chính đối tượng chứa nó

let student = {
       name"Vo Minh Tan",
       getNamefunction() {
              return this.name;
       },
};
console.log(student.getName()); // Vo Minh Tan

2.  This đứng một mình

console.log(this); // [object Window] có thể test ở chrome developer tooll
3. This khi nằm trong một hàm
functionwhoAmI()
{
console.log(this);
}
whoAmI();// [object Window]

4.Trong strict mode


"use strict";
functionwhoAmI()
{
    console.log(this);
}
whoAmI();// undefined

5.Trong event

<button data-id="5"id="btn"onclick="alert(this.getAttribute('data-id'))">Click me</button>

Cơ bản như vậy là quá đủ , và sau đây mới là vấn đề chính :

TRƯỚC khi đi qua các nhầm lần thì mình sẽ giới thiệu sơ qua về các function prototype mà sẽ hỗ trợ các bạn suốt quá trình thao tác với các object

Call – apply – bind trong js :

Hàm call apply và bind là các prototype trong function ( vì trong js thì function cũng chính là object mà object thì có các prototype của nó) , thường thì các prototype này sẽ được dùng rất nhiều trong oop cụ thể là trong inheritance nhưng nó cũng được ứng dụng trong cách khắc một số lỗi this pointer

1.Call

function.call(thisArg, arg1, arg2, ...)

Khi gọi cho phép bạn truyền vào object làm context , param 1 , param 2 là các tham số ứng với function gọi , ví dụ :


var person1 = {firstName'Nguyen', lastName'Thai'};
var person2 = {firstName'Hong', lastName'Thang'};
function fcku(sentence1,sentence2) {
 console.log(sentence1+ ',' + sentence2+ ' ' + this.firstName + ' ' + this.lastName);
}
say.call(person1, 'Hello', 'f*ck you'); // => Hello, f*ck you Nguyen Thai
say.call(person2, 'Hello', 'and f*ck you too'); // => Hello, and f*ck you too Hong Thang


This được gán một context rõ ràng là person1 và person2 và các param được truyền theo thứ tự rõ ràng

2.Apply

fun.apply(thisArg, [argsArray])

Tương tự call nhưng các tham số phía sau đc truyền dưới dạng array
var person1 = {firstName'Nguyen', lastName'Thai'};
var person2 = {firstName'Hong', lastName'Thang'};
 
function fcku(sentence1,sentence2) {
 console.log(sentence1+ ',' + sentence2+ ' ' + this.firstName + ' ' + this.lastName);
}
say.apply(person1, ['Hello', 'f*ck you']); // => Hello, f*ck you Nguyen Thai
say.apply (person2, ['Hello', 'and f*ck you too']); // => Hello, and f*ck you too Hong Thang

3.bind

var newFunction = fun.bind(thisArg[, arg1[, arg2[, ...]]])

Trả về một hàm mới và hàm này có context của thisArg

var person1 = {firstName'Nguyen', lastName'Thai'};
var person2 = {firstName'Hong', lastName'Thang'};
 
function fcku(sentence1,sentence2) {
 console.log(sentence1+ ',' + sentence2+ ' ' + this.firstName + ' ' + this.lastName);
}
say.bind(person1, 'Hello', 'f*ck you'); // => Hello, f*ck you Nguyen Thai
say.bind(person2, 'Hello', 'and f*ck you too'); // => Hello, and f*ck you too Hong Thang
  • Nhìn chung, hàm call và apply là gần giống nhau. Chúng đều gọi hàm trực tiếp. Chỉ khác ở cách truyền tham số vào (với call thì đối số phân cách bởi dấu phẩy và với apply thì đối số cho bởi mảng array)
  • Hàm bind thì hơi khác hơn một chút. Hàm này không gọi hàm trực tiếp mà nó sẽ trả về một hàm mới. Và bạn có thể sử dụng hàm số mới này sau. Về cách truyền tham số vào thì nó giống với hàm call.

Một số lỗi hay gặp khi dùng this

Những điều về this rất cơ bản đã được trình bày ở trên. Tuy nhiên, khi làm việc thực tế, có những trường hợp this trở nên rất khó hiểu và khó nắm bắt. Trong phần này, chúng ta sẽ cùng tìm hiểu những tình huống như vậy, và cách xử lý tương ứng

Đại đa số mọi người đều sẽ sai về “function context” tức là ngữ cảnh trong lúc gọi this , ví dụ câu nói ở trên ta có Thái là còn trai nhưng anh ấy thích trai . Ta dùng được đại từ nhân xưng anh ấy bởi vì trong đây ngữ cảnh lúc này đang nói đến Thái , nhưng nếu ta chỉ để “ anh ấy “ độc lập thì ngữ cảnh lúc này mơ hồ và không rõ ràng -> đây cũng là lỗi nhiều người mắc phải

1.Gán method của object có dùng this  cho một biến mới


var student = {
    firstName"Vo",
    lastName"Minh Tan",
    showFullNamefunction() {
        console.log(this.firstName + " " + this.lastName);
    }
}
var newFunction = student.showFullName;
 
newFunction(); // undifined undifined

Lúc này newFunction sẽ là một function bằng với student.showFullName , tức là content sẽ giống nhau , nhưng “this” thì sao?

Lúc này this sẽ là this trong ngữ cảnh của newFunction , mà this trong ngữ cảnh của 1 function như mình đề cặp lý thuyết 5 rules of THIS thì this sẽ là global object , nhưng firstName không nằm trong global object nên => undifined

CÁCH XỬ LÝ

Dùng bind như giới thiệu ở trên thì newFunction được set context như của student

var newFunction = student.showFullName.bind(student) // Vo Minh Tan

2.Truyền method chứa THIS như một callback

Hãy thử đoán xem đoạn code dưới đây khi click button thì console.log sẽ in ra gì?

Hint :  nhớ dựa vào 5 rules of this nhé

var student = {
    firstName"Vo",
    lastName"Minh Tan",
    showFullNamefunction() {
        console.log(this.firstName + " " + this.lastName);
    }
}
document.getElementById('button').addEventListener("click",student.showFullName);

YES , lại tiếp tục undefined , theo 5 rules of thi trong một event thì this refer đến chính element đó mà element đó không tồn tại firstName => undifined

CÁCH XỬ LÝ

Để đoạn code trên chạy đúng như mong muốn – in ra được name của Student – thì ta phải đảm bảo được context của hàm callback Student.showFullName là chính đối tượng Student lúc hàm này được gọi. Cụ thể trong trường hợp này chúng ta có thể dùng hàm Bind() để gắn context vào callback đó

document.getElementById('button').addEventListener("click",student.showFullName.bind(student));

3. This dùng trong closure

Closure tức là một hàm lồng trong hàm khác(basic closure)

Ta có ví dụ sau

var student = {
    firstName"Vo",
    lastName"Minh Tan",
    showFullNamefunction() {
        console.log(this.firstName)  // Vo
        
        var getLastName = function(){
            console.log(this.lastName)// undefined
        }
 
        getLastName();  
    }
}
student.showFullName();

trong ví dụ trên getLastName là inner function (hàm bên trong) muốn trỏ để this.lastName là điều không thể , ta có this.firstName = Vo thì đúng vì nó trỏ đến object chứa nó , NHƯNG this.lastName thì lại nằm ở getLastName  mà function này không có một context rõ ràng tại vì khi thực thi thì chỉ gọi getLastName(,, nó không có một object nào chứa nó và đại diện để thực thi nó cả => nó chỉ là một function bình thường , không phải là một method của object, tiếp tục căn cứ vào 5 rules of THIS thì this lúc này trỏ đến global window

CÁCH XỬ LÝ

có 3 giải pháp , 1 là dùng biến tạm , 2 là dùng bind , 3 là dùng arrow function

CÁCH 1 : DÙNG BIẾN TẠM

var student = {
    firstName"Vo",
    lastName"Minh Tan",
    showFullNamefunction() {
        console.log(this.firstName)  // Vo
        var that = this;
        var getLastName = function(){
            console.log(that.lastName)// Minh Tan
        }
 
        getLastName();  
    }
}
 
student.showFullName();

CÁCH 2 : DÙNG BIND

Var student = {
    firstName"Vo",
    lastName"Minh Tan",
    showFullNamefunction() {
        console.log(this.firstName)  // Vo
        var getLastName = function(){
            console.log(this.lastName)// Minh Tan
        }.bind(student)
 
        getLastName();  
    }
}
 
student.showFullName();

CÁCH 3 : ARROW FUNCTION

var student = {
    firstName"Vo",
    lastName"Minh Tan",
    showFullName() => {
        console.log(this.firstName)  // Vo
        var getLastName = function(){
            console.log(this.lastName)// Minh Tan
        }
 
        getLastName();  
    }
}
 
student.showFullName();

KẾT

Qua mấy vị dụ trên thì cũng hiểu được đại khái this rồi nhỉ , Chúng ta thấy rằng, hầu hết mọi rắc rối xảy ra với con trỏ this là do dự thay đổi context của hàm và chúng ta có các hàm như apply(), bind(), call() để kiểm soát con trỏ this trong nhiều tình huống khác nhau , mình thấy ứng dụng nó rất oke , nhất là trong lập trình game thì THIS là không thể thiếu , cho nên hãy luôn chú ý đến context của con trỏ this khi hàm được gọi nhé


Share:

Static Web Craping với NodeJS và Cheerio


Chắc hẳn từ khóa này các bạn đã được nghe đến ở đâu đó. Vậy, nó là gì ? Trong bài viết này mình sẽ giới thiệu với các bạn một kĩ thuật khá là hay ho và được giới Developer sử dụng rất nhiều chứ không riêng gì các bạn viết Web.





Web Scraping là kĩ thuật thu thập thông tin của một Website bằng việc request đến url của trang cần lấy dữ liệu và download file html DOM của url đó.





Trong Web Scraping chúng ta đã phần nào sử dụng đến Web Crawler. Vậy 2 thằng này khác nhau như thế nào ? Hai khái niệm này có sự liên quan với nhau. Web Scraping là quá trình thu thập thông tin từ một url cho trước. Còn Web Crawler sẽ download toàn bộ nội dung của trang đồng thời tìm tất cả các liên kết trong trang đó và tiếp tục download chúng, khi thao tác tải hoàn tất data sẽ được đánh chỉ số index rồi add on database. Thông thường ta sử dụng kĩ thuật Scraping để thu một số dữ liệu cần thiết của trang chứ không lấy hết toàn bộ.









Một số việc mà ta có thể áp dụng kĩ thuật này là: lấy data như giá, hình ảnh, comment, ... về sản phẩm của các trang thương mại điện tử và sử dụng với mục đích cá nhân như là so sánh giá của sản phẩm ở các trang thương mại khác hay giá sản phẩm hiện tại và của quá khứ xem chênh lệch như thế nào , ... Ngoài ra cũng còn khá nhiều ứng dụng hay ho về kĩ thuật này, các bạn tự mình khám phá nhé.








* Yêu cầu:





Máy của bạn phải cài môi trường Node 8.0 và phải có npm. Nếu đang dùng phiên bản Node thấp hơn thì bạn hãy tham khảo cách để Update nhé.









Khởi đầu dự án





Các bạn new một thư mới và open code editer tại đó nhé. Tiếp theo các bạn initialize một dự án npm với câu lệnh:





npm init





Sau bước này các bạn sẽ thấy một file có tên là package.json vừa được tạo ra. Sau đó ta cần cài các package sau: request, cheerio, axios bằng câu lệnh:





npm i request cheerio axios dotenv --save




  • package request: dùng để tạo 1 request đến url cần scraping
  • package cheerio: dùng để parser respond của request trả về dưới dạng cấu trúc cây DOM
  • package axios: dùng để gửi request post data lên lưu ở database
  • package dotenv: dùng để cài đặt các biến môi trường








Request URL





Mình sẽ nói sơ qua về cấu trúc thư mục của dự án một tí





Do ở đâu mình sử dụng Editor Visual Studio Code nên khi làm việc nó tạo 1 file .vscode như thế




  • File .env dùng để thiết lập các biến môi trường, các Private key mà các bạn không muốn để người khác biết. Nhớ thêm nó vào File .gitignore để tránh commit nhầm nhé !
  • File scraping.js là file code chính của chúng ta.
  • File package.json và package-lock.json thì quá quen thuộc với các bạn rồi nên mình không nói đến nha.
  • File .gitignore xuất hiện là do mình có git init tại project để sau này deploy lên GIT các bạn có thể tham khảo.






Đầu tiên, file .env có gì:









File này có Format dạng key=value. Ở đây khi biên dịch thì nó trở thành chuỗi cả nên mình không cần để nó trong nháy đơn hay kép gì hết, nếu có nhiều cặp giá trị thì các bạn cứ phẩy rồi viết tiếp





Vậy thì cái value của key ở trên do đâu mà ra thì mình sẽ hướng dẫn các bạn sử dụng thằng mockapi làm server giả để post dữ liệu mình scraping được lưu trữ lên đó nhé. Còn các bạn nếu có Database rùi thì cứ post lên server của các bạn.





Đầu tiên bạn vào trang https://www.mockapi.io và reg cho mình một cái tài khoản. Sau khi các bạn login, tại giao diện chính các bạn new cho mình một cái project và đặt tên gì cũng được.









Giả sử mình tạo như thế. Sau khi tạo xong các bạn chọn Project vừa rồi và New Resource. Ở mục resource name là một endpoint của API, các bạn cũng đặt tên bình thường.
Phần quan trong đây: ở mục schema biểu diễn các trường dữ liệu mà các bạn cần lưu. Ở đây mình sẽ tạo như thế này:









Yeah, Click create nữa là xong.







Bài viết này mình sẽ Demo cách Scraping những bài báo về corona ở trang:
https://thanhnien.vn/tin-tuc/covid-19.html





Đầu tiên ta send 1 request lên url này và lấy html về:





require('dotenv').config();

var request = require('request');

request('https://thanhnien.vn/tin-tuc/covid-19.html', (error, response, html) => {
if (!error && response.statusCode == 200) {
// làm gì đó ở đây
} else {
console.log(error);
}
});




Mục đích của dòng 1 là nhúng cặp key=value vừa rồi ta khai báo ở File .env vào môi trường node. Các bạn có thể kiểm tra xem nó có chưa bằng cách log nó ra xem thử: console.log(process.env."key")





Function request nhận vào 2 tham số là url và function. Ở đây mình viết dưới dạng arrow function. Arrow Func này có 3 giá trị:





  • error: trả về lỗi nếu request đến url không thành
  • respond: trả về respond từ phía url
  • html: html của url đó nếu thành công








Cheerio Load









require('dotenv').config();

var request = require('request');
var cheerio = require('cheerio');

request('https://thanhnien.vn/tin-tuc/covid-19.html', (error, response, html) => {
if (!error && response.statusCode == 200) {
const $ = cheerio.load(html);

$('.relative').find('.story').each((index, story) => {
if (story) {
var image = $(story).find('a').find('img').attr('data-src');
var link = $(story).find('a').attr('href');
var header = $(story).find('h2').find('.story__title').text();
var meta = $(story).find('.meta').find('.timebox').text();
var summary = $(story).find('.summary').find('div').text();

apiAddArticle(api_secret, {
image,
link,
header,
meta,
summary
});
}
})
} else {
console.log(error);
}
});




Sau khi có html ta có nhiều cách để trích xuất những data mà chúng ta muốn. Ở đây mình dùng thằng cheerio để load html đó vào một biến (dòng 8) và sử dụng jQuery selecter để bóc tách. Các bạn cũng có thể dùng selecter của window như document.querySelecterAll, ...





Trước tiên ta hãy xem cấu trúc của trang báo thanh niên đó như thế nào nhé !









Ta thấy, một div có class relative bao tất cả các div có class story mà các div.story này có thể xem như 1 component data mà ta có thể trích xuất. Ví dụ với component đầu tiên thì các dữ liệu ta có thể trích xuất là: thumbnail, header, meta (1 tiếng trước), và một đoạn summary, có thể là số comment nữa.





Với dòng selecter: $('.relative').find('.story') ta sẽ nhận được một mảng các component có class là story nằm trong div.relative. Tiếp theo ta cùng xem bên trong có gì nữa nhé !









Với các thẻ và thuộc tính mà mình hightlight thì các bạn cũng có thể selecter ra được các field mà mình muốn. Các selecter ở dòng 12 đến 16 các bạn có thể xem cấu trúc cây sẽ hiểu hơn nhé.









Request Post to Database









require('dotenv').config();

var request = require('request');
var cheerio = require('cheerio');
var axios = require('axios');

var api_secret = process.env.API_SECRET;

function apiAddArticle(api_secret, data){
axios.post(api_secret, data)
.then(function () {
console.log("Add successed");
})
.catch(function () {
console.log("Add failed");
});
}




Ở mục trên mình có gọi 1 function apiAddArticle() là để gửi 1 request post yêu cầu database add bài báo. Ở đây mình dùng thằng Axios để call API, các bạn có thể cùng thằng nào tùy thích nhé.





Nhớ lấy api_secret ở biến môi trường ra nhé !









Code hoàn chỉnh:









require('dotenv').config();

var request = require('request');
var cheerio = require('cheerio');
var axios = require('axios');

var api_secret = process.env.API_SECRET;

function apiAddArticle(api_secret, data){
axios.post(api_secret, data)
.then(function () {
console.log("Add successed");
})
.catch(function () {
console.log("Add failed");
});
}

request('https://thanhnien.vn/tin-tuc/covid-19.html', (error, response, html) => {
if (!error && response.statusCode == 200) {
const $ = cheerio.load(html);

$('.relative').find('.story').each((index, story) => {
if (story) {
var image = $(story).find('a').find('img').attr('data-src');
var link = $(story).find('a').attr('href');
var header = $(story).find('h2').find('.story__title').text();
var meta = $(story).find('.meta').find('.timebox').text();
var summary = $(story).find('.summary').find('div').text();

apiAddArticle(api_secret, {
image,
link,
header,
meta,
summary
});
}
})
} else {
console.log(error);
}
});








Và đây là kết quả trên server của mình:














Github project: https://github.com/Nguyen-Quoc-Thai/web-scraping/tree/master









Summary





Cherrio sử dụng cấu trúc cây DOM parser rất thân thiện khi sử dụng, nó đặt biệt nhanh và hiệu quả với những trang text nhưng dữ liệu có thể bị thiếu nếu bạn truy cập một trang web phức tạp có nhiều tính năng sử dụng cookie hoặc là các trang web sử dụng AJAX để tương tác với người dùng. Lúc này bạn có thể nghĩ tới việc dùng puppeteer thay vì cheerio mà bài viết trước team mình đã đề cập.






Chúc các bạn thành công !





Writer: Quốc Thái





Follow me via:
Facebook
Github







Share:

Thứ Năm, 7 tháng 5, 2020

Thu Thập Dữ liệu Trang Web (Web Scraping) với PUPPETEER


Khi cần dữ liệu của 1 trang web nào đó, trang web đó có thể cung cấp API cho ta kết xuất thông tin ở dạng JSON. Nhưng trong nhiều trường hợp, nếu không có API thì ta phải đi cào dữ liệu từ trang bằng cách mở Google Dev Tools và code qq gì đó lấy thông tin ở các element trong trang và có trích xuất được dữ liệu. Có khá nhiều công cụ phục vụ cho việc scraping, tùy theo ngôn ngữ bạn sử dụng. Trong bài viết này mình sẽ giới thiệu Puppeteer, một thư viện của Nodejs.





Một số kiến thức bạn cần có trước khi bắt đầu:
+ Javascript, Nodejs
+ Async await trong Javascript
+ Render được 1 trang html đơn giản (có thể sử dụng Pugjs) (có thể biết sau cũng được)





Đầu tiên, chúng ta tạo một project để test nhé (Lưu ý đặt tên khác Puppeteer (tên package) vì khi lưu vào file Package.json sẽ báo lỗi đấy)
+ Mở cửa sổ cmd tại folder project, gõ lệnh npm init: tạo file package.json lưu thông tin project, các module sử dụng...
+ Gõ npm install puppeteer --save





Bước thiết lập project hoàn tất, chúng ta bắt đầu với file index.js và gõ đoạn lệnh chạy thử, bật tab terminal trên IDE để xem các câu lệnh được console.log()





const puppeteer = require('puppeteer'); // add thư viện puppeteer 

(async() => {
// Mở một browser ảo để lấy thông tin
const browser = await puppeteer.launch({headless: false});
console.log('Browser opened');

// Mở một trang có địa chỉ url và đi đến trang web đó
const page = await browser.newPage();
const url = 'https://www.DAMDANG.vn';
await page.goto(url);

console.log('Page loaded');

// set viewport cho browser ảo đó, méo quan trọng lắm
await page.setViewport({ width: 1920, height: 1080 });

// Thực thi lệnh blabla, thu thập dữ liệu trang web

// Đóng browser
await browser.close();
})();





* Các bạn nhớ kiểm tra kĩ và hiểu đoạn code trên nhé, kẻo lỗi...
* Cái {headless: false} sẽ bật lên một brower ảo. Mặc định sẽ là true, tức là không có brower nào được bật lên trên màn hình, nhưng brower đó vẫn được chạy ngầm.






Ví dụ ở bài này mình sử dụng trang thống kê top 100 channel youtube nhiều subscribes nhất: url = "https://vn.noxinfluencer.com/youtube-channel-rank/top-100-vn-all-youtuber-sorted-by-subs-weekly"





Giờ chúng ta vào trang trên, mở Dev Tool (ctrl + shift + I) để xem cấu trúc các element như thế nào.





Ví dụ mình muốn lấy ảnh các channel youtube chẳng hạn, ta thấy rằng nó là 1 thẻ img (với các attribute class='avatar', src="...") nằm trong thẻ td (class='profile'). Để đơn giản trên cửa sổ terminal, chúng ta sẽ console.log() các src đó ra.





Chúng ta sẽ test tại tab Console của Developer Tool (tại trang web thống kê có url trên), paste đoạn lệnh này:





// chọn các node là thẻ img(class='avatar') nằm trong thẻ td(class='profile')
let avatars = document.querySelectorAll('td.profile img.avatar');

// chuyển danh sách node thành 1 mảng (100 phần tử ứng với top 100 channel)
avatars = [...avatars];

// Có thể chuyển sang một mảng mới, với các phần tử là 1 object với key là src
let channel = avatars.map((avatar) => ({
src: avatar.getAttribute('src'),
}));

// In ra để xem có cl gì nhé
console.log(channel);




Test nhanh trên tab Console thành công, bạn có thể paste đoạn lệnh trên vào file index.js rồi chạy câu lệnh 'node index.js'...





const puppeteer = require('puppeteer'); // add thư viện puppeteer 

(async() => {
// Mở một browser ảo để lấy thông tin
const browser = await puppeteer.launch({headless: false});
console.log('Browser opened');

// Mở một trang có địa chỉ url và đi đến trang web đó
const page = await browser.newPage();
const url = 'https://vn.noxinfluencer.com/youtube-channel-rank/top-100-vn-all-youtuber-sorted-by-subs-weekly';
await page.goto(url);

console.log('Page loaded');

// set viewport cho browser ảo đó, méo quan trọng lắm
await page.setViewport({ width: 1920, height: 1080 });

var channels = page.evaluate() => {
let avatars = document.querySelectorAll('td.profile img.avatar');

avatars = [...avatars];

let channels = avatars.map((avatar) => ({
src: avatar.getAttribute('src'),
}));
return channels;
}

console.log(channels);

// Đóng browser
await browser.close();
})();




Không chỉ lấy một thuộc tính như trên mà ta có thể lấy nhiều thông tin hơn đặt cho nó các thuộc tính khác nhau và render ra 1 trang html hay đơn giản như mình làm demo sương sương thế này...









Ngoài ra còn rất nhiều phương thức khác của Puppeteer mà bạn có thể tham khảo tại link github: https://github.com/puppeteer/puppeteer





Happy Hacking!





Người viết: Minh Thắng


Share: