Xây dựng Amazon Price Tracker bằng Python (Cách Thực Tế)
Xây dựng một price tracker hoạt động với Python và Selenium, kèm theo các test thực tế về những gì thực sự khiến bạn bị chặn.
Những điểm chính
- Các trang sản phẩm hiếm khi chặn scraper; trong quá trình kiểm tra, 150 request đã đi qua mà không bị chặn một lần nào.
- Các trang tìm kiếm Amazon chặn ngay ở request đầu tiên, ngay cả khi có proxy.
- Việc bị chặn là do không phải trình duyệt thực, chứ không phải do địa chỉ IP của bạn.
- Cần proxy được ghim vào quốc gia cụ thể để lấy đúng giá địa phương, không chỉ để tránh bị chặn.
Tôi tưởng mình đã tìm được PlayStation 5 rẻ nhất trên internet.
Price tracker của tôi in ra $74,00 bên cạnh một PS5, nhưng nếu điều đó nghe có vẻ quá tốt để là sự thật trên mạng, thì nó gần như luôn luôn là như vậy. $74 đó không phải là console. Đó là scraper lấy nhầm phần tử, và đây chính xác là loại bug thầm lặng khiến hầu hết các hướng dẫn "Amazon price tracker" trở nên vô dụng mà không ai hay biết.
Vì vậy, thay vì chỉ đơn thuần đăng năm mươi dòng Python rồi xem như xong, điều mà hầu hết các hướng dẫn đều làm, tôi đã kiểm tra nó đúng cách. Tôi chạy nó trên Amazon với khối lượng lớn, đo chính xác những gì bị chặn và những gì không, và sửa những bug mà các hướng dẫn không bao giờ đề cập. Kết quả thật sự đáng ngạc nhiên: một scraper đơn giản gửi 150 request đến một trang sản phẩm mà không bị chặn một lần nào, nhưng lại bị chặn ngay ở request đầu tiên khi truy cập trang tìm kiếm.
Hướng dẫn này chính là tracker hoạt động được cộng với mọi thứ mà quá trình kiểm tra đã phát hiện, bao gồm một thủ thuật Selenium rất đáng biết ngay cả khi bạn đã từng xây dựng scraper trước đây: nó điều khiển một cửa sổ Chrome thực sự, theo cách trực quan, để bạn có thể xem trang tải và scrape trong thời gian thực.
Amazon có thực sự chặn bạn không?
Mọi hướng dẫn đều cảnh báo rằng Amazon sẽ chặn scraper của bạn ngay lập tức. Vì vậy tôi đã kiểm tra, và kết quả thực sự khiến tôi bối rối.
Tôi chỉ một scraper trần trụi, không trang bị gì vào trang sản phẩm PlayStation 5 và cứ để nó gửi liên tục. Một request, hai, mười, năm mươi — tôi cứ chờ đợi bức tường chặn. Nó không bao giờ xuất hiện. Cái scraper đó đã gửi 150 request đến cùng một trang và mọi request đều trả về "ok". Tôi không thể tin nó lại mở cổng đến vậy.
Và đúng là như vậy thật. Các trang sản phẩm, hóa ra, hầu như không quan tâm. Sau đó tôi chỉ cùng một scraper vào một trang kết quả tìm kiếm, và nó chết ngay ở request đầu tiên. Không phải cái thứ mười, không phải cái thứ năm mươi. Cái đầu tiên. Một lỗi 503 ngay lập tức.
Trang kết quả tìm kiếm là nơi xảy ra việc thu thập dữ liệu thực sự, vì vậy đó là nơi Amazon tập trung các biện pháp phòng thủ. Các trang sản phẩm riêng lẻ? Hoàn toàn mở.
Đây là những gì tôi đã thử và kết quả:
Trang sản phẩm, scraper đơn giản: 150 request, không bị chặn
Trang tìm kiếm, scraper đơn giản: bị chặn ở request #1 (503)
Trang tìm kiếm, header tốt hơn: vẫn bị chặn ở request #1
Trang tìm kiếm, header + residential proxy: vẫn bị chặn ở request #1
Trang tìm kiếm, trình duyệt thực: hoạt động, 16 kết quả
Trang tìm kiếm, trình duyệt + US proxy: hoạt động, 22 kết quả
Điều khiến tôi ngạc nhiên nhất: dùng residential proxy cho trang tìm kiếm hoàn toàn không giúp được gì. Vẫn bị chặn, ngay request đầu tiên. Vấn đề chặn không bao giờ là về địa chỉ IP của tôi — mà là về việc tôi không phải là trình duyệt thực sự. Ngay khi tôi tải cùng trang tìm kiếm đó trong một trình duyệt thực thay vì một script thô, nó hoạt động:
Xây dựng tracker
Hãy xây dựng nó. Toàn bộ tracker chỉ khoảng 50 dòng Python. Bạn cần Python 3 và Google Chrome được cài đặt, sau đó một lệnh để cài các thư viện:
pip install selenium requests matplotlib
Chỉ nó đến một sản phẩm
Mỗi sản phẩm Amazon có một ID gọi là ASIN — mã 10 ký tự trong URL ngay sau /dp/. Ví dụ, trong amazon.com/dp/B0F1J12R6N, ASIN là B0F1J12R6N. Đó là tất cả những gì tracker cần để tìm một sản phẩm.
Tại sao requests không đủ
Cách hiển nhiên nhất để scrape một trang là thư viện requests của Python: một dòng, lấy HTML, xong. Và đối với trang sản phẩm, nó thậm chí trả về 200 OK. Nhưng đây là cái bẫy tôi đã mắc phải: một 200 không có nghĩa là bạn đã nhận được dữ liệu. Amazon xây dựng giá vào trang bằng JavaScript, và requests không chạy JavaScript. Vì vậy bạn nhận được trang trả về, nhưng giá không có trong đó.
Đó là lý do tại sao tracker này dùng Selenium thay thế. Selenium điều khiển một trình duyệt Chrome thực sự: nó thực sự mở trang, chạy JavaScript, và cho phép bạn đọc kết quả đã được render đầy đủ. Lần đầu tiên bạn chạy nó, Chrome tự mở với một banner thông báo "Chrome is being controlled by automated test software", và bạn xem nó hoạt động trong thời gian thực.
Scrape giá (và bug mà mọi người đều mắc phải)
Đây là nơi hầu hết các hướng dẫn thầm lặng vỡ vụn. Cách tiếp cận phổ biến là lấy phần tử .a-price và đọc text của nó. Vấn đề: Amazon đặt giá trong phần tử đó hai lần — một lần hiển thị, một lần cho screen reader — vì vậy bạn nhận được $449,00$449,00 lộn xộn thay vì một con số rõ ràng.
Cách sửa là nhắm vào bản sao sạch, duy nhất của giá bên trong buy box và đọc nó cẩn thận, kiểm tra giá buy-box chính trước để tránh vô tình lấy giá của một phụ kiện — đó chính xác là cách tôi kết thúc với cái "$74 PS5" đó. Các selector chính xác có trong code trên GitHub.
Khi nó nhắm đúng phần tử, giá trả về sạch sẽ:
Lưu lịch sử và vẽ biểu đồ
Một price tracker chỉ hữu ích nếu nó ghi nhớ. Script lưu mỗi lần đọc vào một file, được phân theo sản phẩm, lưu giá dưới dạng số thực sự cộng với đơn vị tiền tệ, không phải chuỗi "$54,00". Điều đó quan trọng: số thì có thể vẽ biểu đồ, so sánh và tìm giá thấp nhất; chuỗi thì không. Nếu để mặc định, script kiểm tra một lần rồi dừng; thêm tùy chọn lặp và nó sẽ kiểm tra lại theo lịch, xây dựng lịch sử theo thời gian mà một script nhỏ thứ hai có thể biến thành biểu đồ giá theo thời gian.
Bug suýt khiến tôi trả giá: bạn có thể đang scrape nhầm quốc gia
Nhớ cái PlayStation $74 đó không? Đó là dấu hiệu đầu tiên cho thấy có gì đó sai. Dấu hiệu thứ hai còn tệ hơn, vì nó khó phát hiện hơn.
Khi tôi lần đầu chạy tracker mà không có proxy, Amazon không chỉ cho tôi những giá lạ — với một số sản phẩm, nó không cho tôi giá thực nào cả, chỉ là thông báo "mục này không thể giao đến vị trí của bạn". Tracker không có gì hữu ích để ghi lại.
Vì vậy tôi định tuyến nó qua proxy để trông giống như một người mua sắm ở Mỹ. Giá trả về bằng euro. Lúc đầu tôi cho rằng proxy hoàn toàn không hoạt động. Sau đó tôi nhận thấy trang ghi "Giao đến Ireland", và mọi thứ trở nên rõ ràng: proxy hoạt động tốt, nó chỉ đưa tôi vào một IP Ireland. Đúng ý tưởng, sai quốc gia.
Cách sửa là dùng residential proxy được ghim vào quốc gia bạn thực sự quan tâm. Khi tôi khóa nó vào Mỹ, tracker kéo đúng giá — $54,00, bằng đô la, mỗi lần.
Và việc ghim quốc gia đó không phải là thứ có thì tốt — đó là toàn bộ mục đích. Giả sử bạn đang theo dõi giá đối thủ cạnh tranh để quyết định mức giá cho một thị trường cụ thể. Những con số đó chỉ có ý nghĩa nếu chúng là giá mà thị trường đó thực sự thấy. Cùng một sản phẩm có thể là $449 ở Mỹ và €499 ở Ireland. Nếu scraper của bạn thầm lặng trả về giá Ireland, bạn đang đưa ra quyết định cho một thị trường dựa trên dữ liệu của thị trường khác — và vì nó trông có vẻ hợp lệ, không ai phát hiện ra.
Vì vậy proxy ở đây không phải là để lách qua các lớp chặn — kiểm tra của tôi cho thấy các trang sản phẩm hầu như không chặn dù sao. Mà là để đảm bảo dữ liệu bạn thu thập là dữ liệu đúng.
Nếu bạn muốn dữ liệu giá được ghim vào một quốc gia cụ thể, các residential proxy của FlashProxy cho phép bạn nhắm mục tiêu bất kỳ vị trí nào, để bạn luôn thu thập những giá mà thị trường đó thực sự thấy.
Vậy… liệu cái này có nên khó hơn không?
Đây là đánh giá thành thật của tôi: nếu bạn cần scrape giá từ một trang web, bạn không cần đọc hàng trăm blog, xem cả đống video YouTube, hay cứ hỏi đi hỏi lại AI cho đến khi nó cuối cùng ra đúng. Bạn chỉ cần tự làm. Nó cực kỳ dễ, và thành thật mà nói, nó dễ đến mức gần như đáng lo ngại.
Trước khi bắt đầu, tôi nghĩ cái này sẽ khó. Tôi thực sự lo lắng khi chạy các bài kiểm tra đầu tiên mà không có proxy kết nối — tôi đoán mình sẽ bị chặn mãi mãi, hoặc bị rate-limit đến mức không dùng được nữa. Tôi đã chờ đợi hậu quả.
Không có gì xảy ra. Hoàn toàn không có gì. 150 request tại một trang sản phẩm, không proxy, không chặn, không ban, không email tức giận. Bức tường tôi đang chuẩn bị đối mặt hầu như không tồn tại — và nơi duy nhất nó có (trang tìm kiếm), một trình duyệt thực đã đi thẳng qua.
Vì vậy nếu thứ duy nhất ngăn bạn xây dựng một cái là giả định rằng nó khó hoặc rủi ro: thì không phải vậy. Hãy xây dựng nó. Chỉ cần giữ ở mức hợp lý, theo dõi giá công khai, đừng liên tục đánh vào trang, và tôn trọng điều khoản của họ. Còn nỗi sợ? Phần lớn chỉ trong đầu bạn — cũng như nó từng ở trong đầu tôi.
Toàn bộ code
Toàn bộ dự án — tracker, công cụ hỗ trợ proxy, biểu đồ, và các test script — là mã nguồn mở: amazon-price-tracker-python on GitHub. Clone về và chạy, hoặc đọc qua để hiểu chính xác nó hoạt động như thế nào.


