Tải bản đầy đủ (.doc) (30 trang)

Tìm hiểu kiến trúc của search engine framework lucene và ứng dụng nutch

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (713.75 KB, 30 trang )

Bài tập lớn xử lý ngôn ngữ tự nhiên
TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI
VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG
──────── * ───────
BÀI TẬP LỚN
MÔN: XỬ LÝ NGÔN NGỮ TỰ NHIÊN
ĐỀ TÀI: TÌM HIỂU KIẾN TRÚC CỦA SEARCH ENGINE
FRAMEWORK LUCENE & ỨNG DỤNG NUTCH
GVHD: Th.s Hoàng Anh Việt
Nhóm sinh viên:
Nguyễn Thế Anh 20080070
Trần Anh Thơ 20082569
Nguyễn Vương Quyền 20082142
Nguyễn Văn Hưng 20081293
Lớp: Công nghệ phần mềm K53
Hà Nội - 11/2012
1
Bài tập lớn xử lý ngôn ngữ tự nhiên
MỤC LỤC
MỤC LỤC 2
PHẦN I: NGUYÊN LÝ VÀ MÔ HÌNH CHUNG CỦA SEARCH ENGINE 3
1. Giới thiệu chung 3
2. Phân loại 4
2.1. Máy tìm kiếm thông thường 4
2.2. Máy siêu tìm kiếm - Meta Search Engine 4
3. Nguyên lý hoạt động của search engine 5
4. Mô hình của seach engine 6
4.1. Bộ tìm duyệt Crawler 6
4.2. Kho dữ liệu Repository 8
4.3. Bộ lập chỉ mục Indexer 10
4.4. Bộ tìm kiếm thông tin – Search Engine 11


4.5. Phân hạng trang (Page Rank) 13
PHẦN II: FRAMEWORK LUCENE 15
2.1. Các thành phần indexing 16
PHẦN III: ỨNG DỤNG NUTCH 24
2
Bài tập lớn xử lý ngôn ngữ tự nhiên
PHẦN I: NGUYÊN LÝ VÀ MÔ HÌNH CHUNG CỦA SEARCH ENGINE
1. Giới thiệu chung
Máy tìm kiếm Search Engine nguyên thuỷ là một phần mềm nhằm tìm ra các trang
trên mạng Internet có nội dung theo yêu cầu người dùng dựa vào các thông tin mà người
sử dụng cung cấp qua từ khoá tìm kiếm. Máy tìm kiếm sẽ truy tìm trong cơ sở dữ liệu của
nó và trả về danh mục các trang web có chứa từ khoá mà người sử dụng đưa vào ban đầu.
Thuật ngữ “Search Engine” được dùng chung để chỉ 2 hệ thống tìm kiếm: Một do
các chương trình máy tính tự động tạo ra (Crawler-Based Search Engines) và dạng thư
mục Internet do con người quản lý (Human-Powered Directories). Hai hệ thống tìm kiếm
này tìm và lập danh mục website theo 2 cách khác nhau.
Crawler-Based Search Engines: Các máy tìm kiếm loại này chúng sử dụng các
chương trình máy tính, được gọi là Robots, Spiders, hay Crawlers để lần tìm các trang
trên mạng, rồi tự động phân tích các trang lấy về và đưa vào cơ sở dữ liệu của nó. Khi có
một yêu cầu tìm kiếm, các Search Engine đối chiếu từ khóa cần tìm vào trong bảng chỉ
mục và trả về các thông tin lưu trữ tương ứng. Các cỗ máy tìm kiếm loại này có cơ chế
cập nhật nội dung của web định kỳ để phát hiện sự thay đối (nếu có) của các trang web.
Human-Powered Directories: các thư mục Internet hoàn toàn phụ thuộc vào sự
quản lý của con người. Nếu người sử dụng muốn các Search Engine tìm thấy trang web
của mình thì họ phải đăng ký vào thư mục bằng cách gửi bản đăng ký đến ban biên tập
của Search Engine.
Ngày nay hầu hết các hệ thống tìm kiếm đều là sự tổng hợpcủa hệ thống tìm kiếm
tự động và hệ thống tìm theo thư mục do người dùng quản lý.
3
Bài tập lớn xử lý ngôn ngữ tự nhiên

2. Phân loại
Xét theo phương pháp tìm kiếm thì các Search Engine được chia làm hai loại chính: Tìm
kiếm thông thường và siêu tìm kiếm.
2.1. Máy tìm kiếm thông thường
Các máy tìm kiếm thông thường thực hiện công việc tìm kiếm theoqui trình thu
thập tài liệu, phân loại và tạo chỉ mục. Chúng gồm hai loại,Search Engine sử dụng thư
mục chủ đề và Search Engine tạo chỉ mục tự động.
Các Search Engine sử dụng thư mục chủ đề phân lớp sẵn các trangtrên Internet
vào các thư mục chủ đề và theo các cấp chi tiết hơn của chủ đề.
2.2. Máy siêu tìm kiếm - Meta Search Engine
Meta Search Engine là loại máy truy tìm ảo, nó hoạt động dựa trên sự tồn tại của
các Search Engine sẵn có. Các Meta Search Engine không có cơ sở dữ liệu của riêng
mình. Khi có yêu cầu tìm kiếm máy siêu tìm kiếm sẽ gửi từ khóa đến các Search Engine
khác một cách đồng loạt và nhận về các kết quả tìm được. Nhiệm vụ còn lại của máy siêu
tìm kiếm là phân tích và phân hạng lại các kết quả tìm được.
4
Bài tập lớn xử lý ngôn ngữ tự nhiên
3. Nguyên lý hoạt động của search engine
Search engine điều khiển robot đi thu thập thông tin trên mạng thông qua các siêu
liên kết ( hyperlink ). Khi robot phát hiện ra một site mới, nó gởi tài liệu (web page) về
cho server chính để tạo cơ sở dữ liệu chỉ mục phục vụ cho nhu cầu tìm kiếm thông tin.
Bởi vì thông tin trên mạng luôn thay đổi nên robots phải liên tục cập nhật các site
cũ. Mật độ cập nhật phụ thuộc vào từng hệ thống search engine. Khi search engine nhận
câu truy vấn từ user, nó sẽ tiến hành phân tích, tìm trong cơ sở dữ liệu chỉ mục & trả về
những tài liệu thoả yêu cầu.
5
Bài tập lớn xử lý ngôn ngữ tự nhiên
4. Mô hình của seach engine
4.1. Bộ tìm duyệt Crawler
Bộ tìm duyệt Crawler thu thập các trang trên Internet rồi chuyển chobộ đánh chỉ

mục Indexer. Crawler xuất phát từ tập các URL ban đầu S0. Đầutiên nó sắp xếp các phần
tử trong tập S0 vào một hàng đợi, sau đó lấy dầncác URL theo thứ tự và tải về các trang
tương ứng, Crawler trích tất cả cácURL có trong các trang vừa tải về rồi lại đưa vào hàng
đợi. Quá trình trêntiếp tục cho đến khi Crawler quyết định dừng lại. Do số lượng các
trang tảivề rất lớn và tốc độ thay đổi nhanh chóng của Web nên xuất hiện những vấnđề
cần giải quyết:
• Lựa chọn các trang để tải về.
• Cách cập nhật các trang: Crawler phải xem xét trang nào nên ghé thăm lại
trang nào không.
• Song song hoá quá trình dò tìm trang web: Các Crawlers song songphải được
bố trí một cách hợp lý sao cho một Crawler không ghé thăm cáctrang mà một
Crawler khác đã thăm.
4.1.1. Page selection (lựa chọn các trang)
Bộ tìm duyệt Crawler tải về các trang theo thứ tự trang nào “quantrọng” sẽ tải về
trước. Như vậy ta phải tìm hiểu cách mà Crawler xác địnhmức độ quan trọng của các
trang.
Cho một trang web P, ta định nghĩa mức độ “quan trọng” của trang P theo các
cách sau:
- Interest Driven: là phương pháp xác định mức độ quan trọng của các trang dựa
vào mức độ quan tâm của người sử dụng với các trang đó.
- Popularity Driven: xác định mức độ quan trọng của một trang dựa vào mức độ
phổ biến của trang. Một trong các cách để định nghĩa độ phổ biến của trang là
sử đếm số liên kết đến trang đó (số back link).
- Location Driven: xác định mức độ quan trong của trang P dựa vào địa chỉ của
nó.
6
Bài tập lớn xử lý ngôn ngữ tự nhiên
4.1.2 Mô hình Crawler
Crawler được thiết kế để có khả năng ghé thăm các trang theo thứ tựcác trang có
mức độ quan trọng cao hơn thăm trước các trang có hạng thấphơn thăm sau. Bộ Crawler

đánh giá các trang dựa vào giá trị phân hạng.Từsự đánh giá này Crawler biết được các
trang có mức độ quan trọng cao hơnđể lấy về trong lần kế tiếp. Để đánh giá chất lượng
của Crawler người ta cóthể định nghĩa độ đo chất lượng quality metric của nó bằng một
trong haicách sau:
- Crawl & stop: Bộ Crawler C xuất phát từ trang khởi đầu P0 và dừng lại sau khi
ghé thăm k trang, k là số lượng trang mà Crawler có thể tải về trong một lần
duyệt. Một Crawler tốt sẽ ghé thăm các trang theo thứ tự R1,….Rk trongđó R1
là trang có thứ hạng cao nhất, lần lượt đến R2,… . Gọi R1, …,RK là cáctrang
hot. Trong số k trang được Crawler ghé thăm chỉ có m trang (m<=k) sẽđược
sắp thứ hạng cao hơn hoặc bằng trang Rk
- Crawl & Stop with Threshold: vẫn giả sử rằng bộ Crawler ghé thăm ktrang.
Tuy nhiên lúc này đích quan trọng G đã được cho sẵn, và bất cứ trang nào có
độ quan trọng lớn hơn G thì đều được coi là trang hot.
- Độ đo thứ hạng (Ordering Metrics): Một Crawler lưu giữ những URLs mà nó
đã ghé thăm trong quá trình dò tìm vào một hàng đợi. Sau đó nó lựa chọnmột
URL trong hàng đợi cho lần ghé thăm tiếp theo. Ở mỗi lần lựa chọn thì
Crawler chọn URL u có giá trị Orderingcao nhất để ghé thăm. Độ đo thứ hạng
(Ordering Metric) được thiết lập dựa vào một trong các độ đo khác. Ví dụ nếu
ta đang thực hiện tìm những trang có giá trị IB(P) cao, thì ta sẽ lấygiá trị IB’(P)
làm độ đo thứ hạng, trong đó P là trang mà được trang u trỏ tới.
4.1.3 Page Refresh
Khi Crawler lựa chọn và tải về các trang “quan trọng”, sau một khoảng thời gian
nhất định nó phải thực hiện cập nhật các trang đó. Có rất nhiều cách để cập nhật các trang
web, và các cách khác nhau sẽ cho các kếtquả khác nhau. Sau đây là hai cách:
- Uniform refresh policy: Chiến lược cập nhật đồng loạt. Crawler ghé thăm lại
tất cả các trang theo cùng một tần suất f.
- Proportional refresh policy: Cập nhật theo tỷ lệ, một trang thường xuyên thay
đổi thì Crawler ghé thăm thường xuyên hơn. Để chính xác hơn ta giả sử μi là
tần suất thay đổi của trang ei, và fi là tần suất mà Crawler ghé thăm lại trang ei.
Crawler phải ước lượng μi của mỗi trang để thiết lập chiến lược ghé thăm lại mỗi

trang thích hợp.Việc ước lượng này dựa vào quá trình thay đổi của trang trước đó mà
Crawler đã ghi lại được.
Độ đo cập nhật (freshness metric):
Giả sử có hai tập các trang web A, B mỗi tập gồm 20 trang, trong đó tập A có
trung bình 10 trang được cập nhật, tập B có 15 trang được cập nhật. Người ta nói rằng tập
B “cập nhật” hơn (“fresher”) tập A. Thêm nữa nếu tập A được cập nhật một ngày trước
đây, tập B được cập nhật một năm trước đây thì ta nói tập A hiện hành hơn (“more
current”) tập B, dẫn đến khái niệm tuổi “age”:
7
Bài tập lớn xử lý ngôn ngữ tự nhiên
Dựa trên khái niệm trực giác này chúng ta đưa ra định nghĩa freshness và age như sau:
- Freshness: Đặt S={e1,…,en} là tập hợp N trang đã được Crawler tải về.
reshness được định nghĩa như sau: Freshness của trang ei tại thời điểm t là
- Age: Để biết được “tuổi” của một tập chúng ta định nghĩa khái niệm “age” như
sau: “age” của trang ei tại thời điểm t là
A(ei, t)
Freshness và age của tập các trang cục bộ có thể thay đổi theo thời gian. Do vậy
chúng ta cần tính độ freshness trung bình trong một khoảng thời gian dài và sử dụng giá
trị này làm độ freshness của cả tập hợp.
Chiến lược cập nhật Trong một khoảng thời gian nhất định các Crawler chỉ có thể
tải về hoặc cập nhật số lượng giới hạn các trang. Tuỳ thuộc vào chiến lược cập nhật
trang, nguồn download trang sẽ được phân phối cho các trang khác nhau theo các cách
khác nhau.
4.2. Kho dữ liệu Repository
Bộ phận page Repository là một hệ thống lưu trữ có khả năng mở rộng. Hệ thống
này quản lý một tập lớn các trang web. Nó thực hiện hai chức năngchính: chức năng thứ
nhất, cho phép Crawler lưu trữ các trang web. Thứ hai,nó phải cung cấp API truy cập
8
Bài tập lớn xử lý ngôn ngữ tự nhiên
hiệu quả để bộ Indexer và bộ CollectionAnalysis có thể sử dụng để lấy các trang từ kho

dữ liệu.
4.2.1 Các yêu cầu đối với repository
- Một Repository quản lý một tập các đối tượng dữ liệu “data object” lớn.
- Có khả năng mở rộng
- Có cách truy cập kép (dual access mode): Truy nhập ngẫu nhiên được sử dụng
để nhanh chóng nhận về trang web và gán cho mỗi trang một định danh duy
nhất. Truy cập tuần tự được sử dụng để nhận về tập hợp hoàn chỉnh, hay vài
tập hợp con lớn.
- Có thể cập nhật khối lượng lớn.
- Loại bỏ những trang không còn tồn tại.
- Kho dữ liệu được thiết kế phân tán (Distributed Repository).
4.2.2 Nguyên tắc phân tán trang
Các trang có thể được gán cho các nút dựa trên một số nguyên tắc khác nhau. Như
nguyên tắc phân tán đồng bộ (Uniform distribution), tất cả các nút được xử lý đồng nhất.
Một trang có thể được gán cho một nút bất kỳ trong hệ thống. Các nút sẽ chứa các phần
của tập hợp các trang tuỳ theo khả năng lưu trữ của nút. Ngược lại, với cách phân tán
băm (hash distribution) việc định vị các trang vào các nút dựa trên định danh của trang.
4.2.3 Phương pháp tổ chức trang vật lý
Trong một nút đơn, có 3 thao tác có thể thực hiện: thêm trang/chèntrang (page
addition/insertion), truy cập tuần tự tốc độ cao, và truy cập ngẫu nhiên. Cách tổ chức các
trang theo kiểu vật lý tại mỗi nút chính là việc xem xét xem mức độ hỗ trợ mỗi thao tác
trên của nút đó.
4.2.4 Chiến lược cập nhật
Việc thiết kế chiến lược cập nhật phụ thuộc vào tính chất của Crawler. Có hai cách
cấu trúc Crawler: Batch-mode hoặc Steady Crawler: một Crawler kiểu batch-mode được
xử lý định kỳ mỗi tháng một lần, và cho phép duyệt một số lần nhất định (hoặc đến khi
toàn bộ các trang trong tập đích đã được duyệt) sauđó Crawler dừng lại. Với bộ Crawler
như trên thì kho dữ liệu web được cập nhật trong một số ngày nhất định trong tháng.
Ngược lại, một bộ Crawler ổn định (steady Crawler) chạy liên tục, nó liên tục cập nhật và
bổ sung các trang mới cho Repository.

9
Bài tập lớn xử lý ngôn ngữ tự nhiên
4.3. Bộ lập chỉ mục Indexer
Các tài liệu tải về cần phải được xử lý thích hợp trước khi thực hiện việc tìm kiếm.
Việc sử dụng các từ khoá hay thuật ngữ để mô tả nội dung của tài liệu theo một khuôn
dạng ngắn gọn hơn được gọi là tạo chỉ mục cho tài liệu.
Modul Indexer và Collection Analysis có chức năng tạo ra nhiều loại chỉ mục khác
nhau. Modul Indexer tạo ra hai loại chỉ mục chính đó là chỉ mục Text Index (chỉ mục nội
dung) và chỉ mục Structure Index (chỉ mục liên kết). Dựa vào hai loại chỉ mục này bộ
Collection Analysis tạo ra nhiều loại chỉ mục hữu ích khác:
Link Index: tạo chỉ mục liên kết, các đoạn web đã duyệt được biểu diễn dưới dạng
đồ thị với các đỉnh và các cạnh.
Text Index: Phương pháp đánh chỉ mục dựa theo nội dung (text-based) là một
phương pháp quan trọng để định danh các trang có liên quan đến yêu cầu tìm kiếm.
Chỉ mục kết hợp: Số lượng và kiểu của các chỉ mục Utility được quy định bởi bộ
Collection Analysis tuỳ thuộc vào chức năng của bộ máy truy vấn và kiểu thông tin mà
modul Ranking sử dụng.
4.3.1 Các bước lập chỉ mục
Bước 1: Xác định các mục từ, khái niệm có khả năng đại diện cho vănbản sẽ được
lưu trữ.
Bước 2: Xác định trọng số cho từng mục từ, trọng số này là giá trịphản ánh tầm
quan trọng của mục từ đó trong văn bản.
4.3.1.1 Xác định mục từ quan trọng
10
Bài tập lớn xử lý ngôn ngữ tự nhiên
Ta xác định mục từ của một văn bản dựa vào chính nội dung của văn bản đó, hoặc
tiêu đề hay tóm tắt nội dung của văn bản đó.
Thông thường việc lập chỉ mục tự động bắt đầu bằng việc khảo sát tần số xuất
hiện của từng loại từ riêng rẽ trong văn bản.
Đặc trưng xuất hiện của từ vựng có thể được định bởi “thứ hạng-tần số”

(Rank_Frequency) Các bước để xác định một mục từ quan trọng
- Cho một tập hợp n tài liệu, thực hiện tính toán tần số xuất hiện củacác mục từ
trong tài liệu đó.
- Ký hiệu F
ik
(Frequency): là tần số xuất hiện của mục từ k trong tài liệu I
- Xác định tổng tần số xuất hiện TFk (Total Frequency) cho mỗi từbằng cách
cộng những tần số của mỗi mục từ duy nhất trên tất cả n tài liệu.
TF
k
=
- Sắp xếp các mục từ theothứ tự giảm dần của tần số xuất hiện.Chọn một giá trị
làm ngưỡng và loại bỏ tất cả những từ có tổng tầnsố xuất hiện cao hơn ngưỡng
này (stop-word).
4.3.1.2 Tính trọng số của mục từ
Trọng số của mục từ: là tần số xuất hiện của mục từ trong toàn bộ tàiliệu, những từ
thường xuyên xuất hiện trong tất cả các tài liệu thì “ít có ýnghĩa hơn” là những từ chỉ tập
trung trong một số tài liệu.
Ngược lại khi tần số xuất hiện của mục từ k trong tập tài liệu càngcao thì mục từ
đó càng có ý nghĩa.
Lập chỉ mục tự động cho tài liệu là xác định tự động mục từ chỉ mụccho các tài
liệu.Loại bỏ các từ stop-word vì những từ này có độ phân biệtkém và không thể sử dụng
để xác định nội dung của tài liệu.
Bước tiếp theo là chuẩn hoá mục từ, tức là đưa mục từ về dạngnguyên gốc bằng
cách loại bỏ tiền tố, hậu tố, và các biến thể khác của từ nhưtừ ở dạng số nhiều, quá khứ,

4.3.2 Cấu trúc của chỉ mục đảo
Sau khi phân tích các trang web, và thực hiện tách các từ, chuẩn hoá các từ về
dạng nguyên gốc, loại bỏ các từ stop word. Ta thu được một danh mục các từ mỗi từ
được gắn kèm danh sách các trang chứa từ đó. Danh mục này gọi là chỉ mục đảo

(inverted index)
4.4. Bộ tìm kiếm thông tin – Search Engine
Search engine là cụm từ dùng chỉ toàn bộ hệ thống bao gồm các thành phần chính như
bộ thu thập thông tin, bộ lập chỉ mục & bộ tìm kiếm thông tin. Các bộ này hoạt động liên
11
Bài tập lớn xử lý ngôn ngữ tự nhiên
tục từ lúc khởi động hệ thống, chúng phụ thuộc lẫn nhau về mặt dữ liệu nhưng độc lập
với nhau về mặt hoạt động.
Search engine tương tác với user thông qua giao diện web, có nhiệm vụ tiếp nhận &
trả về những tài liệu thoả yêu cầu của user.
Tìm kiếm theo từ khóa là tìm kiếm các trang mà những từ trong câu truy vấn (query)
xuất hiện, ngoại trừ stopword (các từ quá thông dụng như mạo từ a, an, the,…). Về mặt
hiển thị và sắp xếp kết quả trả về, một từ càng xuất hiện nhiều trong một trang thì trang
đó càng được chọn để trả về cho người dùng.Và một trang chứa tất cả các từ trong câu
truy vấn thì tốt hơn là một trang không chứa một hoặc một số từ. Ngày nay, hầu hết các
search engine đều hỗ trợ chức năng tìm cơ bản và nâng cao, tìm từ đơn, từ ghép, cụm từ,
danh từ riêng, hay giới hạn phạm vi tìm kiếm như trên đề mục, tiêu đề, đoạn văn bản giới
thiệu về trang web,…
Ngoài chiến lược tìm chính xác theo từ khoá, các search engine còn cố gắng “hiểu” ý
nghĩa thực sự của câu hỏi thông qua những câu chữ trong truy vấn của người dùng. Điều
này được thể hiện qua chức năng sửa lỗi chính tả, tìm cả những hình thức biến đổi khác
nhau của một từ, ví dụ: search engine sẽ tìm những từ như speaker, speaking, spoke khi
người dùng nhập vào từ speak.
12
Bài tập lớn xử lý ngôn ngữ tự nhiên
4.5. Phân hạng trang (Page Rank)
Sergey Brin và Lawrence Page đã đưa ra một phương pháp nhằm giúp cho công
việc tính toán hạng trang. Phương pháp này dựa trên ý tưởng rằng: nếu có liên kết từ
trang A đến trang B thì đó là một sự tiến cử của trang A đối với trang B. Nếu trang B
được nhiều trang “quan trọng” hơn trỏ đến, còn trang C nào đó được ít trang “quan

trọng” trỏ đến thì B cũng có độ quan trọng hơn C. Giả sử ta có một tập các trang Web với
các liên kết giữa chúng, khi đó ta có một đồ thị với các đỉnh là các trang Web và các cạnh
là các liên kết giữa chúng.
PR được thể hiện với 11 giá trị: từ 0 – 10, chỉ số PR càng cao thì độ uy tính của trang
web đó càng lớn.
Nếu bạn dùng trình duyệt firefox, bạn có thể dụng công cụ SearchStatus tại địa chỉ
. Hoặc bạn có thể vào
để cài đặt công cụ SEOQuake, có thể xem với mọi trình duyệt
Công thức tính PageRank
PR(A) = (1-d) + d(PR(t1)/C(t1) + … + PR(tn)/C(tn)).
- Trong đó PR(A) là Pagerank của trang A
- t1, t2…tn là các trang liên kết tới trang A
- C là số link outbound của trang nguồn t1, t2 …tn đó (link ra ngoài)
- d là hệ số suy giảm (hệ số tắt dần của chuỗi)
13
Bài tập lớn xử lý ngôn ngữ tự nhiên
Ví dụ nhé Page A của bạn có 3 trang page B (PR=6) page C (PR=3) và page D (PR = 4).
Link tới Page B có 3 link dẫn ra ngoài, Page C có 6 link dẫn ra ngoài, Page D có 12 link
dẫn ra ngoài
Vậy PR của A = 0.15 + 0.85*( 6/3 + 3/6 + 4/12) =2 (xấp xỉ)
Một khi đã biết được công thức, ta có thể chủ động hơn khi trao đổi liên kết với các site
khác. Chẳng hạn nếu bạn liên kết với một site PR =7,8 gì đó và site đó chỉ có 1 link
outbound dẫn đến bài viết trên site của ta.
14
Bài tập lớn xử lý ngôn ngữ tự nhiên
PHẦN II: FRAMEWORK LUCENE
1. Giới thiệu
Lucene là một thư viện mã nguồn mở viết bằng java cho phép dễ dàng tích hợp
thêm chức năng tìm kiếm đến bất cứ ứng dụng nào. Nó cung cấp các API hỗ trợ
cho việc đánh chỉ mục và tìm kiếm . Lucene có thể được sử dụng để tích hợp chức

năng tìm kiếm vào ứng dụng sẵn có hoặc xây dựng một search engine hoàn chỉnh
Lucene hỗ trợ các phần sau trong các bước của quá trình tìm kiếm với search
engine
- Phân tích dữ liệu (dạng văn bản) để đánh chỉ mục: Analyze document
- Đánh chỉ mục (Index document & Index)
- Thực hiện việc xây dựng câu truy vấn và tìm kiếm trong chỉ mục: Build query,
render result, run query
Lucene có thể đánh chỉ mục, tìm kiếm bất cứ dạng dữ liệu gì miễn là các dạng dữ
liệu này có thể chuyển về dạng dữ liệu văn bản text. Do đó, Lucene không quan
tâm đến nguồn dữ liệu, định dạng dữ liệu thậm chí cả ngôn ngữ chỉ cần ta có thể
chuyển đổi nó sang dạng văn bản. Nó có thể đánh chỉ mục các dữ liệu của server
từ xa hoặc trên máy cục bộ với các tập tin có định dạng khác nhau như txt, word,
html, pdf…
Hiện tại, Lucene đã được triển trên nhiều ngôn ngữ khác nhau như C#, PHP, C,
C++, Python, Ruby…
2. Lucene trong các thành phần của một ứng dụng tìm kiếm
Phần này sẽ trình bày các thành phần thư viện Lucene hỗ trợ và các thành phần
cần phải được tích hợp thêm để xây dựng một hệ thống search engine hoàn chỉnh.
Như ta sẽ thấy, ứng dụng tìm kiếm sẽ thực hiện các bước truy lục các nội dung
thông tin thô, tạo các tài liệu từ nội dung, tách ra văn bản từ các tài liệu nhị phân
và đánh chỉ mục tài liệu. Khi chỉ mục đã được xây dựng, ta sẽ cần xây dựng một
giao diện tìm kiếm, cách thực thi tìm kiếm và hiển thị kết quả tìm kiếm.
Các ứng dụng tìm kiếm có nhiều biến thể khác nhau. Một số chạy như một thành
phần nhỏ được nhúng vào trong một ứng dụng. Một số có thể chạy trên một
website, một cơ sở hạ tầng server chuyên biệt và tương tác với nhiều người sử
dụng thông qua trình duyệt web hoặc mobile. Số khác có thể chạy trong mạng
intranet của một công ty và tìm kiếm những tài liệu nội bộ trong công ty đó.
15
Bài tập lớn xử lý ngôn ngữ tự nhiên
Nhưng các biến thể này đều có kiến trúc tổng thể giống nhau được minh họa như

hình bên dưới
Ta sẽ lần lượt xem xét các thành phần của hệ thống search engine
2.1. Các thành phần indexing
Giả sử ta chúng ta cần tìm kiếm trên một số lượng lớn các file. Cách tiếp cận
thông thường là duyệt từng file xem có chứa từ hoặc cụm từ ta đưa ra hay không.
Phương pháp này sẽ làm việc nhưng không hiệu quả nếu số lượng file hoặc kích
thước file là quá lớn. Để tìm kiếm hiệu quả hơn, ta cần đánh chỉ mục tập văn bản
16
Bài tập lớn xử lý ngôn ngữ tự nhiên
tìm kiếm, chuyển đổi chúng thành khuôn dạng cho phép ta tìm kiếm nhanh hơn và
loại bỏ tiến trình quét tuần tự. Tiến trình này được gọi là indexing và kết quả đầu
ra của nó gọi là index
Quá trình indexing bao gồm một dãy các bước phân biệt mà chúng ta sẽ lần lượt
làm rõ sau đây.
a. Thu thập nội dung (Acquire content)
Bước đầu tiên là thu thập nội dung (acquire content). Tiến trình này sử dụng
một crawler hoặc spider để thu thập các nội dung cần thiết sẽ được đánh chỉ
mục. Các crawler sẽ chạy liên tục như một dịch vụ để đợi khi có những nội
dung mới hoặc thay đổi, nó sẽ cập nhật các nội dung này.
Lucene như là một thư viện core và nó không cung cấp bất cứ chức năng nào
để hỗ trợ thu thập nội dung. Chúng ta có thể một số thư viện mã nguồn mở sẵn
có để thực hiện chức năng thu thập nội dung thông tin sau
• Solr: Một project con của Apache Lucene hỗ trợ thu thập thông tin
trong CSDL quan hệ, XML feeds, xử lý các tài liệu thông qua Tika
• Nutch: Một project con của Apache Lucene, có một crawler để thu
thập nội dung của các website
• Grub: Một web crawler mã nguồn mở
• Heritrix, Droids, Aperture…
Sau khi thu thập được các nội dung thông tin, chúng ta sẽ tạo ra các phần nhỏ
được gọi là các tài liệu của nội dung

b. Xây dựng tài liệu (Build Document)
17
Bài tập lớn xử lý ngôn ngữ tự nhiên
Khi ta đã có được các nội dung thô, ta phải chuyển các nội dung này thành các
đơn vị (units) thường được gọi là các document được sử dụng bởi search
engine. Document chứa một số trường có tên phân biệt với các giá trị tương
ứng, ví dụ: title, body, abstract, author, url. Chúng ta phải thiết kế cách để chia
các dữ liệu thô thành các tài liệu và các trường cũng như cách để tính giá trị
cho từng trường này. Thông thường, cách tiếp cận khá rõ ràng: một email trở
thành một tài liệu, hoặc một file PDF hoặc một trang web trở thành một tài
liệu. Nhưng trong một số trường hợp thì không rõ ràng như thế, ví dụ: cách xử
lý các file đính kèm trong một email. Liệu chúng ta có nên gộp tất cả các nội
dung text lấy ra từ các file đính kèm thành một document hoặc tạo ra các
document phân biệt
Khi ta làm việc theo các thiết kế này, ta sẽ cần phải lấy ra text từ các nội dung
thông tin thô cho từng tài liệu. Nếu nội dung ban đầu đã ở dạng text bình
thường và kiểu mã hóa được biết trước thì công việc là khá đơn giản. Nhưng
trong trường hợp các tài liệu ở dạng nhị phân (PDF, Microsoft office, Open
office, Adobe flash, streaming video, audio multimedia) hoặc chứa các thẻ (các
thẻo phải được bỏ đi trước khi indexing) (RDF, XML, HTML) thì sao ? Ta sẽ
cần chạy các bộ lọc tài liệu để lấy ra được text từ các nội dung như thế trước
khi tạo search engine document.
Trong bước này cũng có thể cần áp dụng các logic nghiệp vụ để tạo ra các
trường. Ví dụ, nếu ta có một trường “body text” lớn, ta có thể chạy những bộ
phân tích ngữ nghĩa để lấy ra các thuộc tính như tên, vị trí, ngày, thời gian, vị
trí… để đưa vào các trường thích hợp.
Lucene cung cấp API để xây dựng các trường và các document nhưng nó
không cung cấp bất cứ logic nào để xây dựng một document. Nó cũng không
cung cấp bất cứ document filter nào. Ta có thể sử dụng thêm các thư viện như
Tika để thực hiện chức năng document filter.

Sau khi tách ra được các document và các trường text thì search engine vẫn
chưa thể đánh chỉ mục được ngay mà còn phải thông qua giai đoạn phân tích
văn bản
c. Phân tích tài liệu (analyze document)
Không có search engine nào đánh chỉ mục trực tiếp text, đúng hơn là text phải
được chia nhỏ thành một dãy các phần tử nguyên tử được gọi là token. Bước
phân tích tài liệu sẽ thực hiện nhiệm vụ này. Từng token có thể coi là một từ
trong ngôn ngữ và bước này sẽ xác định cách những trường văn bản trong một
document được phân chia thành một dãy các token.
18
Bài tập lớn xử lý ngôn ngữ tự nhiên
Lucene cung cấp một tập các bộ phân tích được xây dựng sẵn, chúng sẽ giúp
bạn kiểm soát quá trình phân tích dễ dàng hơn. Bước cuối cùng là đánh chỉ
mục cho document
d. Đánh chỉ mục tài liệu (Index document)
Trong bước tiếp theo, document được thêm vào chỉ mục. Lucene cung cấp mọi
điều cần thiết cho bước này với các API đơn giản.
2.2. Các thành phần tìm kiếm (Components for searching)
Searching là quá trình tìm kiếm các từ trong một chỉ mục để tìm những tài liệu nơi
mà các từ đó xuất hiện. Chất lượng của tìm kiếm được mô tả dựa trên 2 độ đo là
precision và recall. Recall đo chất lượng của kết quả tìm ra có phù hợp hay không
trong khi precision đo mức độ loại bỏ các tài liệu không phù hợp. Chúng ta hãy
lần lượt xem các thành phần tìm kiếm của một search engine
a. Search user interface
User interface là phần mà người sử dụng tương tác trực tiếp trên trình duyệt,
ứng dụng desktop hoặc thiết bị di động khi họ tương tác với ứng dụng tìm
kiếm. Lucene không cung cấp bất cứ giao diện tìm kiếm mặc định nào, nó phải
được chúng ta tự xây dựng. Khi mà người sử dụng submit yêu cầu tìm kiếm,
nó phải được dịch ra thành đối tượng Query phù hợp cho search engine
b. Xây dựng truy vấn (Build query)

Khi người sử dụng dùng search engine để tìm kiếm, họ sẽ submit yêu cầu tìm
kiếm lên server. Sau đó, yêu cầu này phải được dịch thành đối tượng Query
của search engine. Chúng ta gọi bước này là build query
Các đối tượng Query có thể đơn giản hoặc phức tạp. Lucene cung cấp một gói
được gọi là QueryParser để biến câu truy vấn người sử dụng nhập vào thành
đối tượng Query theo cú pháp tìm kiếm. Truy vấn có thể chứa các toán tử
boolean, những truy vấn cụm hoặc những ký tự đại diện. Ngoài ra, truy vấn có
thể thêm vào các ràng buộc để hạn chế các tài liệu người sử dụng đó được phép
truy vấn. Một số ứng dụng cũng có thể sửa đổi câu truy vấn để thay đổi thứ tự
kết quả tìm kiếm hoặc lọc những phần quan trọng, nếu boosting (thao tác thay
đổi trọng số của các chỉ mục giúp hiển thị kết quả theo độ ưu tiên theo yêu cầu)
không được thực hiện khi indexing. Thông thường, một website thương mại
điện tử sẽ boost các loại sản phẩm mang lại lợi nhuận nhiều hơn hoặc filter các
sản phẩm.
QueryParser mặc định của Lucene thường đáp ứng được yêu cầu của một ứng
dụng thông thường. Đôi khi, chúng ta sẽ muốn sử dụng đầu ra của QueryParser
và cộng thêm các logic riêng để hiệu chỉnh lại đối tượng Query. Bây giờ chúng
ta có thể sẵn sàng để thực thi yêu cầu tìm kiếm
19
Bài tập lớn xử lý ngôn ngữ tự nhiên
c. Search Query
Search Query là quá trình tra cứu chỉ mục tìm kiếm và lấy ra các tài liệu khớp
với Query được sắp xếp theo thứ tự yêu cầu. Thành phần này bao đóng các
công việc phức tạp bên trong của search engine và Lucene xử lý tất cả chúng
cho bạn. Lucene cũng có thể mở rộng ở điểm này nên khá đơn giản nếu ta
muốn tùy biến cách kết quả được thu thập, lọc, sắp xếp…
Có 3 mô hình lý thuyết thông thường của tìm kiếm
• Mô hình logic thuần túy (Pure Boolean model): Các tài liệu chỉ có 2
trạng thái hoặc khớp hoặc không khớp đối với truy vấn yêu cầu và
chúng không được chấm điểm. Trong mô hình này không có điểm

tương ứng với tài liệu khớp và các tài liệu khớp là không được sắp xếp,
một truy vấn sẽ chỉ nhận diện được các bộ phù hợp
• Mô hình không gian vector (Vector space model): Cả các truy vấn và
documents được mô hình hóa như các vector trong không gian nhiều
chiều. Sự phù hợp giữa một câu truy vấn và một tài liệu được tính toán
bởi một số đo khoảng cách vector giữa các vector này
• Mô hình xác suất (Probabilistic model): Trong mô hình này, ta phải tính
xác suất mà một tài liệu khớp với một câu truy vấn sử dụng cách tiếp
cận xác suất đầy đủ
Cách tiếp cận của Lucene kết hợp mô hình không gian vector và mô hình logic
thuần túy và cho phép chúng ta quyết định xem mô hình nào sẽ được sử dụng.
Cuối cùng, Lucene trả lại các tài liệu mà chúng ta sẽ hiển thị ra danh sách kết
quả cho người dùng
d. Render results
Khi chúng ta nhận được bộ các document khớp với truy vấn đã được sắp xếp
theo thứ tự phù hợp thì chúng ta có thể hiển thị chúng đến giao diện người
dùng.
Đến đây, chúng ta đã kết thúc việc xem xét các thành phần của quá trình indexing
và searching trong ứng dụng search nhưng vẫn chưa hoàn thành.
3. Các lớp chính của Lucene
3.1. Các lớp chính đánh chỉ mục
Một số lớp chính để thực thi việc đánh chỉ mục bao gồm
• IndexWriter
• Directory
• Analyzer
• Document
• Field
Hình bên dưới chỉ ra vai trò của các lớp trên tham gia vào quá trình đánh chỉ mục
20
Bài tập lớn xử lý ngôn ngữ tự nhiên

Dưới đây là mô tả ngắn gọn chức năng của các lớp trên
a. IndexWriter
IndexWriter là thành phần trung tâm của quá trình đánh chỉ mục. Lớp này sẽ
tạo ra một chỉ mục mới hoặc mở một chỉ mục đã tồn tại để thêm, cập nhật, xóa
các tài liệu (Document) trong chỉ mục đó. IndexWriter là một lớp cho phép
chúng ta ghi lên chỉ mục nhưng không cho phép chúng ta đọc hoặc tìm kiếm
trên chỉ mục. IndexWriter cần một nơi nào đó để ghi chỉ mục và nơi đó gọi là
Directory
b. Directory
Lớp này mô tả vị trí chứa chỉ mục của Lucene. Directory là một lớp trừu tượng
cài đặt các phương thức chung cho các lớp con. Ví dụ: Chúng ta có thể sử dụng
FSDirectory.open để lấy thể hiện cụ thể FSDirectory của Directory, lớp này
cho phép ta lưu trữ các file chỉ mục trong một thư mục của hệ thống file.
IndexWriter không thể đánh chỉ mục trực tiếp cho text trừ khi text được chia
nhỏ thành các từ phân biệt sử dụng Analyzer
c. Analyzer
Trước khi văn bản (text) được đánh chỉ mục, nó sẽ được xử lý bởi một
Analyzer. Analyzer được xác định trong phương thức khởi tạo của
IndexWriter, nó có nhiệm vụ tách ta các tokens nào sẽ được đánh chỉ mục và
loại bỏ phần còn lại. Nếu nội dung được đánh chỉ mục không phải là plain text
thì ta phải tách plain text ra trước khi đánh chỉ mục. Để thực hiện nhiệm vụ
tách plain text ra ta có thể sử dụng Tika. Analyzer là một lớp trừu tượng nhưng
Lucene cung cấp một vài cài đặt cụ thể của nó. Một số cài đặt thực hiện loại bỏ
các stop word (các từ thông thường được sử dụng, không giúp phân biệt được
các tài liệu với nhau VD: a, an, is, it…), một số thực hiện chuyển đổi các token
thành chữ thường để tìm kiếm không phân biệt chữ hoa, chữ thường. Các
Analyzer là các thành phần quan trọng trong Lucene và có thể được sử dụng
cho nhiều mục đích khác nữa ngoài nhiệm vụ lọc các ký tự đầu vào.
21
Bài tập lớn xử lý ngôn ngữ tự nhiên

Tiếp theo, tiến trình đánh chỉ mục đòi hỏi một tài liệu (Document) chứa các
trường phân biệt (Field)
d. Document
Lớp này mô tả tập hợp các trường (Field). Document có thể được coi như một
tài liệu ảo như một trang web, một thông điệp email hoặc một file text… Các
trường của tài liệu mô tả tài liệu hoặc các siêu dữ liệu gắn với tài liệu đó. Các
nguồn dữ liệu gốc như một trường trong CSDL, một file microsoft office, một
chương của một ebook là không phù hợp cho việc đánh chỉ mục trong Lucene.
Chúng ta phải tách ra được các văn bản từ các tài liệu nhị phân trên và thêm nó
vào như một thể hiện của Field để Lucene có thể xử lý. Các Field có thể là các
siêu dữ liệu như author, title, content, date…
Lucene chỉ xử lý các dữ liệu xâu và số, tức là nó chỉ hỗ trợ các kiểu
java.lang.String, java.io.Reader và các kiểu số thông thường như int, float,
double, long…
Một Document là một container chứa nhiều Field và một Field là lớp chứa nội
dung văn bản được đánh chỉ mục
e. Field
Từng Document là một chỉ mục chứa một hoặc nhiều Field được đặt tên được
đại diện bởi lớp Field. Từng Field có một tên, giá trị tương ứng và một tập các
lựa chọn để kiểm soát cách mà Lucene sẽ đánh chỉ mục giá trị của Field. Một
tài liệu có thể chứa nhiều hơn một Field cùng tên. Trong trường hợp này các
giá trị của các field sẽ được nối với nhau trong khi đánh chỉ mục theo thứ tự
các field được thêm vào document.
3.2. Các lớp chính tìm kiếm
Các lớp được cung cấp để thực hiện chức năng tìm kiếm cũng khá đơn giản.
Dưới đây là một số lớp chính
• IndexSearcher
• Term
• Query
• TermQuery

• TopDocs
a. IndexSearcher
IndexSearcher có nhiệm vụ tìm kiếm các chỉ mục được đánh bởi IndexWriter.
Có thể xem IndexSearcher như là một lớp mở chỉ mục theo kiểu read only. Nó
yêu cầu một thể hiện Directory nắm giữ các chỉ mục đã được tạo ra trước đó và
nó cũng cung cấp một số các phương thức tìm kiếm. Phương thức tìm kiếm
22
Bài tập lớn xử lý ngôn ngữ tự nhiên
đơn giản nhất yêu cầu 2 tham số là đối tượng Query và số lượng kết quả được
trả lại, phương thức này sẽ trả lại đối tượng TopDocs
VD:
b. Term
Một Term là một đơn vị cơ bản cho tìm kiếm. Tương tự như đối tượng Field,
nó bao gồm một cặp giá trị xâu là tên của field và giá trị của field đó. Trong
khi tìm kiếm, ta có thể xây dựng đối tượng Term và sử dụng chúng cùng với
TermQuery
Đoạn code trên hướng dẫn Lucene tìm top 10 tài liệu chứa từ “lucene” trong
trường contents, sắp xếp các tài liệu bởi mức độ phù hợp giảm dần.
c. Query
Query là một lớp trừu tượng, nó chứa một số phương thức tiện ích và phương
thức được sử dụng nhiều là setBoost(float), nó sẽ nói với Lucene rằng truy vấn
này có trọng số cao hơn truy vấn kia. Ngoài ra, Lucene cung cấp một số lượng
các lớp con của lớp trừu tượng Query như: TermQuery, BooleanQuery,
PhraseQuery, PrefixQuery, PhrasePrefixQuery…
d. TermQuery
TermQuery là kiểu cơ bản nhất của truy vấn được hỗ trợ bởi Lucene và nó là
một trong các kiểu truy vấn nguyên thủy. Nó được sử dụng để tìm kiếm các tài
liệu chứa các trường với giá trị phù hợp với truy vấn.
e. TopDocs
TopDocs là lớp mô tả bộ giá trị kết quả được trả về sau khi tìm kiếm. Nó là

một container chứa các con trỏ trỏ đến N kết quả được xếp hạng cao nhất.
Trong đó kết quả là các tài liệu khớp với truy vấn yêu cầu. Với từng bản ghi
trong N kết quả, TopDocs ghi lại các giá trị docID sẽ được sử dụng để lấy ra
các giá trị Document và các điểm trọng số của các tài liệu tương ứng
23
Bài tập lớn xử lý ngôn ngữ tự nhiên
PHẦN III: ỨNG DỤNG NUTCH
1. Giới thiệu về Nutch
1.1. Định nghĩa
Nutch là một search engine mã nguồn mở cài đặt trên ngôn ngữ lập trình
Java. Nutch cung cấp tất cả các công cụ cần thiết để cho phép bạn tạo ra một
search engine (SE) của riêng bạn.
Cài đặt Nutch trên một trong các quy mô: hệ thống file cục bộ, intranet
hoặc trên một web nào đó.Cả ba cách cài đặt đó đều có những đặc tính khác
nhau.Ví dụ: thu thập hệ thống file là đáng tin cậy hơn hai cách cài đặt kia vì có thể
lỗi mạng xảy ra hay bộ nhớ cache không có sẵn.
Các vấn đề với Nutch: Thu thập thông tin cần tìm kiếm trên hàng tỉ trang
web cần giải quyết một vấn đề là chúng ta sẽ bắt đầu từ đâu? Bao nhiêu lần thì
chúng ta thu thập lại? Chúng ta sẽ phải xử lí các trường hợp như link bị hỏng, các
sites không hồi đáp và các nội dung trùng lặp hay khó hiểu? Có một tập các thách
thức để cung cấp khả năng tìm kiếm mở rộng và xử lí hàng trăm câu truy vấn đồng
thời trên một tập dữ liệu lớn
1.2. Đặc điểm
1.2.1. Hỗ trợ nhiều protocol
Hiện nay Nutch hỗ trợ các các protocol khác nhau như: http, ftp, file.
Nhờ kiến trúc plugin-based, ta có thể dễ dàng mở rộng ra thêm các
protocol cho Nutch
1.2.2. Hỗ trợ nhiều loại tài liệu khác nhau
Hiện nay, Nutch có thể phân tách (parse) khá nhiều loại tài liệu khác nhau như:
• Plain text

• HTML
• XML
24
Bài tập lớn xử lý ngôn ngữ tự nhiên
• JavaScript: không chỉ phân tách các link từ mã js như các search
engine khác mà còn phân tách cả phần code của js.
• Open Office (OpenOfice.org): phân tách tài liệu Open Office và Star
Office.
• Tài liệu Microsoft: Word (.doc), Excel(.xls), Power Point(.ppt).
• Adobe PDF
• RSS
• Rich text format document (.rft)
• MP3: phân tách các trường D3v1 hay ID3v2 chứa các nội dung về bài
hát như: tựa đề, album, tác giả…
• ZIP
Mặc định Nutch chỉ xử lý hai loại tài liệu là HTML và Plain Text. Muốn mở
rộng ra cho các tài liệu khác, ta phải cấu hình lại Nutch. Cũng nhờ vào kiến
trúc Plugin-based của Nutch mà ta có thể viết thêm các Plugin để xử lý các tài
liệu khác
1.2.3. Chạy trên hệ thống phân tán
Nutch được phát triển trên nền tảng Hadoop. Do vậy ứng dụng Nutch sẽ
phát huy được sức mạnh của nó nếu chạy trên một Hadoop cluster
1.2.4. Linh hoạt với plugin
Nhờ kiến trúc plugin-based, ta có thể dễ dàng mở rộng các tính năng của
Nutch bằng cách phát triển thêm các plugin. Tất cả các thao tác phân tách tài
liệu, lập chỉ mục và tìm kiếm đều thật sự được thực hiện bởi các plugin
1.3. Nutch và Lucene
Nutch được xây dựng trên phần ngọn của Lucene, một API cho việc đánh
chỉ mục và tìm kiếm văn bản. Một câu hỏi thường thấy là “Ta lên sử dụng Lucene
hay Nutch?” câu trả lời đơn giản ở đây là bạn sử dụng Lucene nếu bạn không cần

một bộ thu thập dữ liệu web . Một kịch bản phổ biến là bạn có một cơ sở dữ liệu
web mà bạn muốn tìm kiếm. Cách tôt nhất là để làm điều này là bạn đánh chỉ mục
trực tiếp từ cơ sở dữ liệu sử dụng Lucene API và sau đó cài đặt giải thuật để tìm
kiếm chỉ số, lại sử dụng Lucene. Nutch thì phù hợp hơn với những websites mà
bạn không thể truy cập trực tiếp đến tầng dữ liệu hoặc nó đến từ các nguồn dữ
liệu rời rạc.
2. Các nền tảng phát triển của Nutch
2.1. Lucene
25

×