Hướng dẫn craw a website page php năm 2024

Thu thập dữ liệu (crawl data) là một thuật ngữ không có gì là xa lạ trong ngành marketing, Dịch Vụ Seo. Vì crawl là kỹ thuật mà các robots của các công cụ tìm kiếm phổ biến hiện nay sử dụng như Google, Yahoo, Bing, Yandex, Baidu… Crawler có công việc chính là thu thập dữ liệu từ một trang web bất kì, hoặc chỉ định trước rồi phân tích cú pháp mã nguồn HTML để đọc dữ liệu và bóc tách thông tin dữ liệu theo yêu cầu mà người dùng đặt ra hoặc các dữ liệu mà Search Engine yêu cầu.

Laravel Dusk là gì

Laravel Dusk là một công cụ tự động hóa trình duyệt do Laravel cung cấp. Nó có khả năng truy cập ứng dụng web của bạn hoặc bất kỳ trang web nào khác trong trình duyệt, tương tự như một người dùng thực tế đang điều hành trang web của bạn. Mặc dù mục đích chính của Laravel Dusk là kiểm tra tự động hóa,tuy nhiên nó cũng có thể được sử dụng để quét web.

Cài đặt Laravel Dusk

Việc cài đặt Laravel Dusk khá là đơn giản. Chúng ta có thể sử dụng composer để làm việc đó :

composer require --dev laravel/dusk

Sau khi package đã được cài, chúng ta có thể dùng lệnh artisan để cài đặt và sinh ra các file mặc định :

Nếu với mỗi website lại viết 1

Define here the models for your scraped items

#

See documentation in:

https://docs.scrapy.org/en/latest/topics/items.html

import scrapy class CrawlerItem(scrapy.Item):

# define the fields for your item here like:
# name = scrapy.Field()
url = scrapy.Field()
title = scrapy.Field()
content = scrapy.Field()
date = scrapy.Field()
6 để phân tích thông tin thì sẽ rất mất thời gian, nhất là với các website tin tức, có hàng ngàn các website tin tức khác nhau và chúng còn mọc ra mỗi ngày.

Vậy bây giờ có một bài toán đặt ra là cần phân tích nội dung của 1000 website báo chí, và nhiệm vụ của chúng ta là phải lập lịch crawl 1000 website báo chí này hàng ngày. Việc lập lịch thì chúng ta có thể tạm giải quyết bằng

Define here the models for your scraped items

#

See documentation in:

https://docs.scrapy.org/en/latest/topics/items.html

import scrapy class CrawlerItem(scrapy.Item):

# define the fields for your item here like:
# name = scrapy.Field()
url = scrapy.Field()
title = scrapy.Field()
content = scrapy.Field()
date = scrapy.Field()
7, vậy còn crawl 1000 website thì sao, không thể viết cả 1000

Define here the models for your scraped items

#

See documentation in:

https://docs.scrapy.org/en/latest/topics/items.html

import scrapy class CrawlerItem(scrapy.Item):

# define the fields for your item here like:
# name = scrapy.Field()
url = scrapy.Field()
title = scrapy.Field()
content = scrapy.Field()
date = scrapy.Field()
6 để parse từng website được! Vậy bài viết này chúng ta sẽ cùng tìm hiểu thêm cách sử dụng cơ sở dữ liệu để lưu cấu hình, cụ thể trong bài viết này sẽ sử dụng MySQL.

Có thể có nhiều bạn thắc mắc là phân tích nội dung của 1000 website báo chí để làm gì? Bài toán này chủ yếu là để phân tích trend, từ khóa, sự kiện hot theo từng ngày, phân tích các nội dung, cho biết trang nào hay đăng lại bài của trang khác, các trang nào là các trang báo uy tín để gợi ý cho người dùng và còn ty tỷ thứ khác nữa.

Tạo project và định nghĩa Item

Tạo một project Scrapy và một

Define here the models for your scraped items

#

See documentation in:

https://docs.scrapy.org/en/latest/topics/items.html

import scrapy class CrawlerItem(scrapy.Item):

# define the fields for your item here like:
# name = scrapy.Field()
url = scrapy.Field()
title = scrapy.Field()
content = scrapy.Field()
date = scrapy.Field()
9 news giống như bài viết

1

0:

Định nghĩa các thuộc tính cần lấy của một bài viết tin tức, bài viết này mình lấy 3 thuộc tính là URL, tiêu đề, nội dung và thời gian:

1

1

Các bạn muốn lấy thêm như là tác giả, hình ảnh, video, danh sách bài viết liên quan,… thì có thể định nghĩa thêm các trường cần lấy và viết thêm đoạn code tương ứng trong

Define here the models for your scraped items

#

See documentation in:

https://docs.scrapy.org/en/latest/topics/items.html

import scrapy class CrawlerItem(scrapy.Item):

# define the fields for your item here like:
# name = scrapy.Field()
url = scrapy.Field()
title = scrapy.Field()
content = scrapy.Field()
date = scrapy.Field()
9.

Thiết kế cơ sở dữ liệu

Chúng ta lấy đại diện một website để phân tích, ở đây mình lấy kenh14. Vào trang chủ của kenh14 trước:

Hướng dẫn craw a website page php năm 2024

Chúng ta thấy các trang báo mỗi trang đều có một trang chủ để chứa danh sách các bài viết, danh sách các bài viết này có thể là danh sách các bài viết nổi bật hoặc danh sách tất cả bài viết sắp xếp theo thứ tự mới nhất tùy vào từng trang. Vì thế nên việc lấy bài viết từ trang chủ có thể không đủ bài viết và tạp nham vì là kết hợp của rất nhiều nhãn. Vậy chúng ta sẽ đi lấy bài viết theo từng nhãn, tùy vào từng bài toán cần giải quyết có thể chắt lọc để lấy ra các dữ liệu cần thiết, ví dụ bài toán bạn muốn phân tích về trend hàng ngày thì crawl bài viết từ các nhãn giải trí, thế giới, đời sống, truyền thông chứ không cần thiết phải crawl các bài viết từ nhãn pháp luật và xe. Các nhãn của website được thể hiện chính là các thanh menu của từng website.

Project của chúng ta đang là lập lịch để crawl hàng ngày vì vậy không giống như project Crawl Alonhadat phải next có khi tới 4000 trang để lấy dữ liệu đủ cho mô hình học máy hay học sâu thì với những project dạng này nếu là lập lịch chạy hàng ngày thì chỉ cần lấy bài viết mới nhất của ngày hôm nay hoặc cùng lắm chạy quá thêm 2-3 ngày nữa. Trong project này tại mỗi nhãn mình chỉ crawl bài viết trong

1

3 tìm thấy và lập lịch crawl lại

1

4. Nhiều bạn sợ sẽ bị trùng bài viết, nhưng đây không phải vấn đề quá lớn, chúng ta có thể lấy url của bài viết xong HASH ra để làm ID cập nhật vào cơ sở dữ liệu (Postgre, Elasticsearch,…) vì thế những bài viết trùng key sẽ được cập nhật mà không bị thêm thành nhiều bản ghi trong CSDL. Còn nếu crawl bị thiếu thì phải tính tới việc giảm tần suất từ 1h xuống còn 30p, 20p hoặc là tăng lượng bài viết mỗi lần crawl từ 1 trang lên 2-3 trang.

Mình thiết kế CSDL cho project này với 3 bảng:

  • Bảng 1 5:

Hướng dẫn craw a website page php năm 2024

  • Bảng 1 6:

Hướng dẫn craw a website page php năm 2024

  • Bảng 1 7:

Hướng dẫn craw a website page php năm 2024

Với trường hợp mình xét tới trong project này là các trường hợp đơn gian nhất đó là các page danh sách bài viết của các nhãn của từng website có cấu trúc giống nhau và các page chi tiết bài viết của từng website cũng chỉ có 1 loại.

Ví dụ trang vietnamnet thì các trang vietnamnet.vn/vn/thoi-su, vietnamnet.vn/vn/kinh-doanh, vietnamnet.vn/vn/giai-tri, vietnamnet.vn/vn/the-gioi đều có cấu trúc website giống nhau nên bảng

1

6 chỉ cần chỉ cần chứa ID của website và lưu thêm x_path thẻ bao bao bên ngoài danh sách bài viết.

Bảng

1

7 thì khá dễ hiểu rồi, khi vào tớ một trang chi tiết thì nó là x_path để lấy ra từng thông tin chúng ta cần. Ở đây mình cũng xét một trường hợp đơn giản là một website chỉ có một loại trang chi tiết bài viết.

Kết nối cơ sở dữ liệu

Cài đặt thư viện để kết nối tới CSDL cho python:

pip3 install mysql-connector-python

0

Có cơ sở dữ liệu rồi thì giờ phải viết thêm một đoạn Code để kết nối tới CSDL cho project Scrapy.

Tạo file

pip3 install mysql-connector-python

1 để lưu lại thông tin về CSDL:

pip3 install mysql-connector-python

2

File

pip3 install mysql-connector-python

3 sẽ lấy các thông tin tương ứng từ CSDL:

pip3 install mysql-connector-python

4

Viết Spider

Nếu mọi người theo dõi series này của mình thường xuyên thì sẽ thấy khi mình viết

Define here the models for your scraped items

#

See documentation in:

https://docs.scrapy.org/en/latest/topics/items.html

import scrapy class CrawlerItem(scrapy.Item):

# define the fields for your item here like:
# name = scrapy.Field()
url = scrapy.Field()
title = scrapy.Field()
content = scrapy.Field()
date = scrapy.Field()
9 thường có sử dụng 3 hàm:

pip3 install mysql-connector-python

6 để chuẩn bị các đường link danh sách bài viết, hàm

pip3 install mysql-connector-python

7 để lấy danh sách link chi tiết bài viết từ trang danh sách bài viết và hàm

pip3 install mysql-connector-python

8 để lấy thông tin cần thiết từ trang chi tiết bài viết.

Hàm

pip3 install mysql-connector-python

6

1 2 3 4 5

0

Hàm này tạo URL từng nhãn của các website từ dữ liệu trong CSDL (các dữ liệu trong CSDL các bạn xem thêm trong phần thiết kế CSDL ở bên trên), các link này chính là các link danh sách bài viết, ví dụ bản ghi đầu tiên có

1 2 3 4 5

1 và

1 2 3 4 5

2 thì sẽ đi từng nhãn một ghép lại thành một url hoàn chỉnh

1 2 3 4 5

3,

1 2 3 4 5

4,

1 2 3 4 5

5,

1 2 3 4 5

6 các URL này chính là URL danh sách bài viết của từng nhãn, giờ gửi chúng xuống hàm

1 2 3 4 5

7 để làm việc tiếp theo.

Hàm

1 2 3 4 5

7

1 2 3 4 5

9

Ở hàm

HOST = "localhost" USER = "root" PASSWORD = "mysql12345" DATABASE = "x_news" PORT = "3306"

0 chúng ta đã có gửi thêm tham số

HOST = "localhost" USER = "root" PASSWORD = "mysql12345" DATABASE = "x_news" PORT = "3306"

1 xuống.

HOST = "localhost" USER = "root" PASSWORD = "mysql12345" DATABASE = "x_news" PORT = "3306"

2 giúp chúng ta tìm được

HOST = "localhost" USER = "root" PASSWORD = "mysql12345" DATABASE = "x_news" PORT = "3306"

3 của phần tử bao bên ngoài danh sách bài viết qua bảng

1

6. Sử dụng hàm

HOST = "localhost" USER = "root" PASSWORD = "mysql12345" DATABASE = "x_news" PORT = "3306"

5 đã viết trong phần kết nối CSDL để lấy ra

HOST = "localhost" USER = "root" PASSWORD = "mysql12345" DATABASE = "x_news" PORT = "3306"

3 tương ứng, lấy ra danh sách URL của từng bài viết và gọi tới hàm

pip3 install mysql-connector-python

8 cuối cùng.

Lưu ý là vẫn cần gửi

HOST = "localhost" USER = "root" PASSWORD = "mysql12345" DATABASE = "x_news" PORT = "3306"

2 xuống hàm

pip3 install mysql-connector-python

8 để có thể lấy các thông tin

HOST = "localhost" USER = "root" PASSWORD = "mysql12345" DATABASE = "x_news" PORT = "3306"

3 trong bài viết được định nghĩa trong CSDL tại bảng

1

7.

Hàm

pip3 install mysql-connector-python

8

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

3

Hàm này thì khá rõ ràng với mục đích của nó rồi, với từng

HOST = "localhost" USER = "root" PASSWORD = "mysql12345" DATABASE = "x_news" PORT = "3306"

3 tương ứng trong CSDL lấy ra dữ liệu tương ứng và trả về

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

5.

Chạy và lập lịch project

Bài viết nằm trong series về Crawl nên mình cũng nói chủ yếu về crawl và cách lưu trữ để crawl mà ít nói về luồng của nó.

Các bạn có thể theo dõi đầy đủ project với luồng dữ liệu từ

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

6 tại https://github.com/trannguyenhan/X-news (Source code này cũng từ khá lâu, một số các cái liên quan tới Kibana, ElastichSearch cũng không được cập nhật lên repo nên các bạn dùng tham khảo là chính thôi nha)

Chạy project với câu lệnh:

Project này mình đang viết file pipeline với đầu ra dữ liệu được đẩy vào một hàng đợi

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

7 để một bên khác nhận và xử lý dữ liệu phía sau, file

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

8 được viết như dưới đây:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

9

Toàn bộ project Crawl này các bạn có thể tham khảo tại link GITHUB: https://github.com/demanejar/crawler-1000news

Để lập lịch cho con

Define here the models for your scraped items

#

See documentation in:

https://docs.scrapy.org/en/latest/topics/items.html

import scrapy class CrawlerItem(scrapy.Item):

# define the fields for your item here like:
# name = scrapy.Field()
url = scrapy.Field()
title = scrapy.Field()
content = scrapy.Field()
date = scrapy.Field()
9 chạy hàng ngày có thể sử dụng

Define here the models for your scraped items

#

See documentation in:

https://docs.scrapy.org/en/latest/topics/items.html

import scrapy class CrawlerItem(scrapy.Item):

# define the fields for your item here like:
# name = scrapy.Field()
url = scrapy.Field()
title = scrapy.Field()
content = scrapy.Field()
date = scrapy.Field()
7, cái này hoạt động khá đơn giản, copy lệnh chạy vào file nó quét qua là được. Xem thêm về

import mysql.connector from crawler.spiders import constants db = mysql.connector.connect(

host=constants.HOST,
user=constants.USER,
password=constants.PASSWORD,
database=constants.DATABASE,
port=constants.PORT
) cursor = db.cursor()

get all website in database

def get_all_websites():

cursor.execute("select * from websites")
rows = cursor.fetchall()
result = []
for row in rows: 
    result.append(row)
return result
# get all url categories of website def get_categories(website_id):
cursor.execute("select * from x_path_categories where website_id = " + str(website_id))
rows = cursor.fetchall()
result = []
for row in rows: 
    result.append(row[2])
return result
# get x_path of title, content of url website def get_contents(website_id):
cursor.execute("select * from x_path_contents where website_id = " + str(website_id))
rows = cursor.fetchall()
result = []
for row in rows: 
    result.append({"title": row[2], "content": row[3], "date": row[4]})
return result
2 tại

Vì website không có mục bình luận dưới bài viết nên mọi người thảo luận và góp ý cho mình tại GITHUB DISCUSSION này nha: https://github.com/orgs/demanejar/discussions/1