Dự án này được xây dựng nhằm mục đích tự động hóa quy trình thu thập dữ liệu đề thi TOEIC Speaking từ nền tảng Study4. Mục tiêu cuối cùng là chuyển đổi dữ liệu thô từ web thành định dạng Markdown sạch đẹp, dễ đọc, và có cấu trúc rõ ràng để phục vụ việc lưu trữ, tra cứu và luyện tập offline.
Điểm nổi bật là khả năng duy trì trạng thái đăng nhập (session) để tránh phải đăng nhập thủ công liên tục và khả năng xử lý/làm sạch dữ liệu văn bản tự động.
Dự án đã trải qua các bước phát triển để đạt được kết quả là kho dữ liệu trong folder data_markdown/:
- Authentication: Thực hiện đăng nhập một lần và lưu trữ session cookie.
- Crawling: Tự động truy cập danh sách URL, tìm link bài thi thật (real exam) và bóc tách dữ liệu 5 phần thi.
- Renaming: Chuẩn hóa tên file theo định dạng dễ quản lý (
slug-id_ID). - Transformation: Chuyển đổi JSON sang Markdown, đồng thời làm sạch văn bản (tách từ dính, xóa prefix thừa) và cảnh báo các phần cần kiểm tra thủ công.
Dưới đây là danh sách các file mã nguồn chính và nhiệm vụ của chúng:
| Tên File | Chức năng (Nhiệm vụ) | Dữ liệu Đầu vào (Input) | Dữ liệu Đầu ra (Output) |
|---|---|---|---|
auth.js |
Mở trình duyệt để người dùng đăng nhập thủ công, sau đó lưu trạng thái phiên làm việc (cookies, local storage) để dùng lại. | Thông tin đăng nhập của người dùng (nhập trên UI). | File state.json (chứa session state). |
urls.js |
Chứa danh sách các URL gốc của các bài thi TOEIC Speaking cần thu thập. | N/A (Hardcoded list). | Array các URL string. |
scrape.js |
Script chính thực hiện việc duyệt qua các link trong urls.js, xử lý logic để vào trang làm bài, và cào dữ liệu của 5 Items. |
urls.js, state.json. |
Các file JSON thô trong folder data/ (Ví dụ: sw-speaking-test-1-id_5895.json). |
convert_to_md.js |
Chuyển đổi và làm sạch data. Biến JSON thành Markdown, fix lỗi dính chữ (regex), và thêm cảnh báo cho phần bảng biểu phức tạp (Item 4). | Các file JSON trong data/. |
Các file Markdown hoàn chỉnh trong folder data_markdown/. |
rename_files.js (deprecated) |
Tiện ích đổi tên file trong folder data để đảm bảo tên file chứa cả slug (tên bài) và id bài thi cho dễ nhận diện. |
Các file trong data/, urls.js. |
File được đổi tên trong data/. |
verify_data.js (test only) |
Kiểm tra và xác nhận các file Markdown đã được chuyển đổi đúng định dạng và không có lỗi. | Các file Markdown trong data_markdown/. |
File verified.md chứa danh sách các file đã được xác nhận. |
- Cài đặt dependencies:
npm install
- Đăng nhập (Chạy 1 lần đầu):
node auth.js
- Thu thập dữ liệu:
node scrape.js
- Chuyển đổi sang Markdown:
node convert_to_md.js
-
Khi chạy
node auth.js:- Bạn cần đăng nhập thành công trên trình duyệt, sau đó quay lại terminal và nhấn ENTER để script lưu lại file session.
- Hãy chú ý dòng nhắc trong terminal như sau:
Navigating to study4.com... Please log in manually in the browser window. Once you have successfully logged in, press ENTER in this terminal to save the session state and exit. Press ENTER to save state... -
Về file
state.json:- Đây là file chứa session (cookies/local storage) của trình duyệt cụ thể được Playwright tạo ra.
- Nó không mang tính tái sử dụng đa nền tảng (không thể copy sang máy khác hoặc trình duyệt khác để dùng trực tiếp nếu không cùng environment).
-
Xử lý lỗi Timeout khi Crawl (
node scrape.js):- Khi chạy
node scrape.js, đôi khi bạn sẽ gặp lỗiTimeoutError(do mạng chậm hoặc server phản hồi lâu), dẫn đến việc thiếu file dữ liệu. - Ví dụ về đoạn log báo lỗi:
Processing: https://study4.com/tests/5907/toeic-sw-speaking-test-13/ Generated Real Exam URL: https://study4.com/tests/5907/practice/?part=14655&... Error processing https://study4.com/tests/5907/toeic-sw-speaking-test-13/: page.waitForLoadState: Timeout 30000ms exceeded. at /Path/To/scrape.js:80:24 { name: 'TimeoutError' }- Cách khắc phục: Hãy chạy lại script.
- Mẹo tối ưu: Để tiết kiệm thời gian, hãy cập nhật file
urls.jsvà chỉ giữ lại những đường dẫn bị lỗi. Ví dụ:
module.exports = [ // ... xóa các link đã thành công ... "https://study4.com/tests/5907/toeic-sw-speaking-test-13/", "https://study4.com/tests/5937/toeic-sw-speaking-test-29/" ];
- Khi chạy
Bên cạnh dữ liệu Speaking, dự án cũng hỗ trợ thu thập và xử lý dữ liệu cho kỹ năng Writing.
| Tên File | Chức năng (Nhiệm vụ) | Dữ liệu Đầu vào (Input) | Dữ liệu Đầu ra (Output) |
|---|---|---|---|
urls-writing.js |
Chứa danh sách các URL gốc của các bài thi TOEIC Writing cần thu thập. | N/A (Hardcoded list). | Array các URL string. |
scrape-writing.js |
Script thực hiện việc cào dữ liệu Writing (tương tự scrape.js nhưng logic bóc tách riêng cho Writing). |
urls-writing.js, state.json. |
Các file JSON thô trong folder data-writing/. |
convert_to_md_writing.js |
Chuyển đổi JSON Writing sang Markdown với format chuẩn: tách email thành blockquote/code block, format lại essay prompt. | Các file JSON trong data-writing/. |
Các file Markdown hoàn chỉnh trong folder data_markdown_writing/. |
Tương tự như Speaking, bạn cần có file state.json từ bước đăng nhập trước đó.
- Thu thập dữ liệu Writing:
node scrape-writing.js
- Chuyển đổi sang Markdown:
node convert_to_md_writing.js
Script convert sẽ tự động format 3 phần thi của Writing thành các header chuẩn:
- Write a sentence: Hiển thị danh sách ảnh.
- Respond to a written request: Hiển thị email trong
code blockđể giữ nguyên format xuống dòng. - Write an opinion essay: Hiển thị câu hỏi essay trong
blockquote.