Hellu mọi người. Hôm nay em xin giới thiệu một thư viện khá chuyên dụng mà chắc hẳn ai từng làm QC cũng đều sử dụng qua, đó chính là Selenium.
1. Selenium là gì?
Selenium là một thư viện giúp cho lập trình viên có thể tự động hóa quá trình kiểm thử, giả lập một người dùng và kiểm tra và thực hiện các thao tác trên một trang web hay một ứng dụng như một người dùng thật. Theo định nghĩa mà em search được trên Google:
“Selenium Webdriver thực hiện mọi automate tương tác với các trình duyệt nhằm hướng tiếp cận hiện đại và ổn định hơn. Quá trình tương tác trình duyệt đều sẽ được gửi trực tiếp từ Selenium Webdriver mà không thông qua Javascript như Selenium RC. Ưu điểm của nó là: Có thể thực hiện Communicate trực tiếp với trình duyệt.”
Đúng là như vậy, nhưng có lẽ không nhiều người biết được công dụng khác của thư viện này, đó chính là khả năng Crawl Data của một ứng dụng nào đó.
2. Tại sao lại là Selenium?
Vì sao có rất nhiều thư viện hỗ trợ cho việc Crawling Data như Colly, Agouti hay Scrappy chuyên dụng thì hà cớ chi mà ta phải sử dụng Selenium?? Thực ra sau một quá trình tìm hiểu thì em thấy rằng trên thị trường hiện nay, đa số các trang web đều là web động, tức là nội dung hoặc giao diện có thể thay đổi dựa trên tương tác của người dùng, dữ liệu từ cơ sở dữ liệu, hoặc các sự kiện khác. (Ví dụ các website bán hàng trực tuyến, v.v). Selenium có khả năng tương tác trực tiếp với các trang web động mà Scrapy hay Colly không thể xử lý một cách dễ dàng. Điều này là do Selenium giả lập một trình duyệt thực sự và có thể chạy JavaScript, trong khi Scrapy thu thập nội dung tĩnh từ trang web. Vì lí do này em cảm thấy việc sử dụng Selenium dần trở thành một ưu thế mạnh mẽ hơn để lấy dữ liệu từ những trang web lớn. Ngoài ra Selenium cũng có rất nhiều những điểm mà Selenium ưu việt hơn các thư viện khác, nhưng chúng ta nên cân nhắc và tìm hiểu về trang web mà ta muốn crawl để có thể lựa chọn sử dụng thư viện nào một cách tối ưu nhất nhé!
3. Setup & Installation:
Em có demo một đoạn Code về cách sử dụng Selenium khá đơn giản bằng Golang như dưới đây:
Trước tiên chúng ta cần import package cho project:
go get -t -d github.com/tebeka/selenium
Package này yêu cầu chúng ta cài đặt WebDriver, mọi người có thể tìm hiểu cách cài WebDriver ở đây nha:
Sau đó chúng ta tiếp tục cài đặt những Dependencies cho Selenium:
cd vendor
go run init.go --alsologtostderr --download_browsers --download_latest
cd ..
Đây là một số các function chính mà em hay sử dụng trong quá trình xử lý và lấy dữ liệu:
// FindElement finds exactly one element in the current page's DOM.
FindElement(by, value string) (WebElement, error)
// GetCookie returns the named cookie in the jar, if present. This method is
// only implemented for Firefox.
GetCookie(name string) (Cookie, error)
// Text returns the text of the element.
Text() (string, error)
// Click clicks on the element.
Click() error
// SendKeys types into the element.
SendKeys(keys string) error
// Submit submits the button.
Submit() error
// Clear clears the element.
Clear() error
cũng có rất nhiều những function và các công dụng khác, mọi người có thể tìm hiểu thêm ở đây:
https://pkg.go.dev/github.com/tebeka/selenium
4. Source Code:
Sau đây là một đoạn Code ngắn mà em viết để crawl tất cả các sản phẩm với từ khóa “điện thoại” trên Lazada ạ:
package main
import(
"fmt"
"github.com/tebeka/selenium"
"github.com/tebeka/selenium/chrome"
"log"
"time"
)
func main(){
// Setup Chrome Driver.
service, err := selenium.NewChromeDriverService("/Users/apple/Downloads/chromedriver-mac-x64/chromedriver", 4444)
if err != nil {
panic(err)
}
defer service.Stop()
caps := selenium.Capabilities{}
caps.AddChrome(chrome.Capabilities{Args: []string{
"window-size=1920x1080",
"--no-sandbox",
"--disable-dev-shm-usage",
"disable-gpu",
}})
// driver: WebDriver.
driver, err := selenium.NewRemote(caps, "")
if err != nil {
panic(err)
}
driver.SetPageLoadTimeout(20 * time.Second)
// Đây sẽ là đường link URL của Lazada mà chúng ta sẽ thực hiện Crawl nhé
driver.Get("https://www.lazada.vn/catalog/?spm=a2o4n.home.search.1.4ff23bdc9Mgm7c&q=dien%20thoai&_keyori=ss&from=search_history&sugg=dien%20thoai_0_1")
// Lấy ra tất cả các sản phẩm điện thoại có class name là "Bm3ON".
elements, err := driver.FindElements(selenium.ByClassName, "Bm3ON")
lis := make([]DtoPhones, 0)
/*
Đoạn code này em chuyển đổi từ Raw Data sang dạng có thể chuyển vào Database
hoặc sử dụng cho mục đich khác, em set là DtoPhones (Data Transfer Object).
*/
for i := 0; i < len(elements); i++ {
// Phần code này em thực hiện việc tìm kiếm data qua Class trên HTML của trang web.
nameItem, _ := elements[i].Text()
price, _ := elements[i].FindElement(selenium.ByClassName, "aBrP0")
priceItem, _ := price.Text()
sold, _ := elements[i].FindElement(selenium.ByClassName, "_1cEkb")
soldAmount, _ := sold.Text()
vote, _ := elements[i].FindElement(selenium.ByClassName, "qzqFw")
voteText, _ := vote.Text()
voteNumber, _ := strconv.ParseInt(voteText, 10, 64)
// Set type cho data này thành DtoPhones.
newPhones := DtoPhones{
itemId: int64(i + 1),
name: nameItem,
price: priceItem,
soldAmount: soldAmount,
voteNumber: voteNumber,
}
fmt.Println("this is the sold amount: ", newPhones.soldAmount)
fmt.Println("this is the item name: ", newPhones.name)
fmt.Println("this is the item price: ", newPhones.price)
fmt.Println("this is the vote number: ", newPhones.voteNumber)
lis = append(lis, newPhones)
}
/*
Ở phần này em muốn thực hiện việc sang trang mới để tiếp tục quá trình lấy dữ liệu.
*/
linksElement, err := driver.FindElements(selenium.ByXPATH, "//div[@class='e5J1n']/ul[@class='ant-pagination']/li")
if err != nil {
fmt.Println("Error getting path:", err)
return
}
var count = 0
for count < len(linksElement) {
for _, elem := range linksElement {
title, err := elem.GetAttribute("title")
if err != nil {
log.Printf("Failed to get title for element: %v", err)
continue
}
fmt.Println("Page:", title)
if err := driver.Click(); err != nil {
log.Printf("Failed to click on the page %s: %v",title, err)
} else {
log.Printf("Click success")
}
count++
}
}
}
Sau khi chạy thì chương trình sẽ log ra như thế này:
!
Mong bài viết này mọi người có thể biết thêm về cách sử dụng Selenium. Nếu có thắc mắc hoặc cần giải thích rõ thêm chỗ nào thì anh/chị có thể hỏi dưới phần comment.