Bạn crawl vài nghìn bài báo trên Google Scholar, PubMed hay Scopus cho một đợt literature review, nhưng cứ vài request lại dính CAPTCHA? CaptchaAI giải tự động reCAPTCHA v2, reCAPTCHA v3 và Cloudflare Turnstile ngay trong pipeline crawl, để bạn tập trung vào phân tích dữ liệu thay vì canh giải CAPTCHA bằng tay.
Các nhóm review tài liệu, trắc lượng thư mục hay meta-analysis đều cần thu thập dữ liệu quy mô lớn — hầu hết cổng tạp chí, cơ sở dữ liệu học thuật chặn truy cập tự động bằng CAPTCHA.
Chỉ thu thập dữ liệu công khai (metadata, tóm tắt, trích dẫn) và tuân thủ điều khoản sử dụng của từng nguồn. Nếu tập kết quả có dữ liệu cá nhân, ghi log truy cập theo Nghị định 13/2023/NĐ-CP.
Nguồn dữ liệu học thuật hay gặp CAPTCHA
| Nguồn | Loại CAPTCHA | Yếu tố kích hoạt | Dữ liệu |
|---|---|---|---|
| Google Scholar | reCAPTCHA v3 | Truy vấn khối lượng lớn | Trích dẫn, bài báo |
| PubMed | reCAPTCHA v2 | Tìm kiếm lặp lại | Tài liệu y sinh |
| Web of Science | Cloudflare Turnstile | Tải hàng loạt | Số liệu trích dẫn |
| Scopus | reCAPTCHA v2 | Thao tác export | Dữ liệu thư mục |
| IEEE Xplore | reCAPTCHA v2 | Tìm kiếm + tải xuống | Bài báo kỹ thuật |
| JSTOR | reCAPTCHA v2 | Truy cập trang | Nhân văn/khoa học xã hội |
Nhiều nhóm data tại các công ty product và outsourcing ở TP.HCM, Hà Nội dùng chung pipeline này để gom trích dẫn cho báo cáo R&D nội bộ — chỉ cần metadata công khai, không cần tài khoản thư viện trả phí.
Giới hạn tần suất request theo từng nguồn học thuật
Đặt độ trễ theo danh sách dưới đây trước khi chạy script kế tiếp — trang học thuật cấm IP rất nhanh nếu phát hiện traffic bất thường:
- Google Scholar — 10–15 giây/request, tối đa 40–50 trang/giờ
- PubMed — 3–5 giây/request, tối đa 100 trang/giờ
- Web of Science — 5–10 giây/request, tối đa 60 trang/giờ
- Scopus — 5–10 giây/request, tối đa 60 trang/giờ
- IEEE — 3–5 giây/request, tối đa 100 trang/giờ
- JSTOR — 5–10 giây/request, tối đa 60 trang/giờ
Script Python thu thập trích dẫn và tự động giải CAPTCHA
import requests
import time
import re
from bs4 import BeautifulSoup
import csv
CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"
def solve_captcha(method, sitekey, pageurl, **kwargs):
data = {
"key": CAPTCHAAI_KEY, "method": method,
"googlekey": sitekey, "pageurl": pageurl, "json": 1,
}
data.update(kwargs)
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data=data)
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(5)
result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY, "action": "get",
"id": task_id, "json": 1,
})
r = result.json()
if r["request"] != "CAPCHA_NOT_READY":
return r["request"]
raise TimeoutError("Timeout")
class AcademicScraper:
def __init__(self, proxy=None):
self.session = requests.Session()
if proxy:
self.session.proxies = {"http": proxy, "https": proxy}
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
})
def search_papers(self, search_url, query, max_pages=10):
"""Search academic database for papers matching query."""
all_papers = []
for page in range(max_pages):
url = f"{search_url}?q={query}&start={page * 10}"
resp = self.session.get(url, timeout=30)
# Handle CAPTCHA
if self._has_captcha(resp.text):
resp = self._solve_and_retry(resp.text, url)
papers = self._parse_results(resp.text)
if not papers:
break # No more results
all_papers.extend(papers)
print(f"Page {page + 1}: {len(papers)} papers")
time.sleep(5) # Respectful delay
return all_papers
def get_paper_details(self, paper_url):
"""Get detailed metadata for a single paper."""
resp = self.session.get(paper_url, timeout=30)
if self._has_captcha(resp.text):
resp = self._solve_and_retry(resp.text, paper_url)
soup = BeautifulSoup(resp.text, "html.parser")
return {
"title": self._safe_text(soup, "h1, .article-title"),
"authors": self._safe_text(soup, ".authors, .author-list"),
"abstract": self._safe_text(soup, ".abstract, #abstract"),
"doi": self._safe_text(soup, ".doi, [data-doi]"),
"journal": self._safe_text(soup, ".journal-name, .publication"),
"year": self._safe_text(soup, ".pub-date, .year"),
"citations": self._safe_text(soup, ".citation-count, .cited-by"),
}
def export_to_csv(self, papers, filename):
"""Export collected papers to CSV."""
if not papers:
return
keys = papers[0].keys()
with open(filename, "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=keys)
writer.writeheader()
writer.writerows(papers)
print(f"Exported {len(papers)} papers to {filename}")
def _has_captcha(self, html):
return any(tag in html.lower() for tag in [
'data-sitekey', 'g-recaptcha', 'cf-turnstile',
])
def _solve_and_retry(self, html, url):
match = re.search(r'data-sitekey="([^"]+)"', html)
if not match:
return self.session.get(url)
sitekey = match.group(1)
if 'cf-turnstile' in html:
token = solve_captcha("turnstile", sitekey, url)
return self.session.post(url, data={"cf-turnstile-response": token})
else:
token = solve_captcha("userrecaptcha", sitekey, url)
return self.session.post(url, data={"g-recaptcha-response": token})
def _parse_results(self, html):
soup = BeautifulSoup(html, "html.parser")
papers = []
for item in soup.select(".gs_r, .search-result, article.result"):
title_el = item.select_one("h3 a, .result-title a")
if title_el:
papers.append({
"title": title_el.get_text(strip=True),
"url": title_el.get("href", ""),
"snippet": self._safe_text(item, ".gs_rs, .abstract-snippet"),
"authors": self._safe_text(item, ".gs_a, .author-info"),
})
return papers
def _safe_text(self, soup, selector):
el = soup.select_one(selector)
return el.get_text(strip=True) if el else ""
# Usage — Literature review
scraper = AcademicScraper(
proxy="http://user:[email protected]:5000"
)
papers = scraper.search_papers(
"https://scholar.example.com/scholar",
query="machine learning CAPTCHA solving",
max_pages=5,
)
# Get details for top papers
detailed = []
for paper in papers[:20]:
if paper["url"]:
detail = scraper.get_paper_details(paper["url"])
detailed.append(detail)
time.sleep(3)
scraper.export_to_csv(detailed, "literature_review.csv")
Mở rộng thành mạng lưới trích dẫn (bibliometric)
def bibliometric_analysis(scraper, seed_papers, depth=2):
"""Follow citations to build a citation network."""
visited = set()
network = []
def _crawl(paper_url, current_depth):
if current_depth > depth or paper_url in visited:
return
visited.add(paper_url)
try:
details = scraper.get_paper_details(paper_url)
network.append(details)
# Follow "cited by" links
resp = scraper.session.get(f"{paper_url}/citations", timeout=30)
if scraper._has_captcha(resp.text):
resp = scraper._solve_and_retry(resp.text, f"{paper_url}/citations")
citations = scraper._parse_results(resp.text)
for cite in citations[:5]: # Limit breadth
if cite["url"]:
_crawl(cite["url"], current_depth + 1)
time.sleep(3)
except Exception as e:
print(f"Error crawling {paper_url}: {e}")
for paper in seed_papers:
_crawl(paper["url"], 0)
return network
Xử lý sự cố khi giải CAPTCHA trên trang học thuật
- Dính CAPTCHA ở mọi lượt tìm kiếm — IP bị trang học thuật gắn cờ; đổi proxy, tăng độ trễ lên trên 15 giây.
- Không trả về kết quả nào — trang trả về CAPTCHA thay vì dữ liệu; kiểm tra CAPTCHA trước khi parse HTML.
- Thiếu phần tóm tắt (abstract) — nội dung nằm sau paywall; dùng proxy tổ chức hoặc bản open access.
- Google Scholar chặn hẳn IP — vượt giới hạn tần suất request; đợi khoảng 30 phút rồi đổi sang IP khác.
- Giới hạn số lượng export — trang giới hạn tải hàng loạt; tải theo từng đợt nhỏ hơn.
Câu hỏi thường gặp
Thu thập metadata từ Google Scholar, PubMed, Scopus có hợp pháp không?
Có, với dữ liệu công khai như tiêu đề, tác giả, tóm tắt; toàn văn còn tùy giấy phép nhà xuất bản. PubMed có API E-utilities chính thức — ưu tiên dùng trước khi crawl HTML.
Giải CAPTCHA trên JSTOR, IEEE Xplore hay Web of Science tốn bao nhiêu?
CaptchaAI tính phí theo thread, không theo từng lần giải. Gói BASIC ($15/tháng, 5 thread) giải không giới hạn số lần mỗi thread — đủ cho hầu hết nhóm nghiên cứu nhỏ.
PubMed có API chính thức để khỏi cần giải CAPTCHA không?
Có — E-utilities là REST API miễn phí của NCBI, không cần giải CAPTCHA nếu tuân thủ rate limit. Dùng CaptchaAI cho các nguồn chưa có API tương đương như JSTOR hay IEEE Xplore.
Script trong bài có xử lý được reCAPTCHA v3 không?
Có. Hàm solve_captcha() dùng chung method userrecaptcha cho cả v2 và v3 — không cần đổi logic code giữa hai phiên bản.
Có cần giải CAPTCHA cho mọi request không?
Không. Hàm _has_captcha() chỉ gọi CaptchaAI khi phát hiện data-sitekey, g-recaptcha hoặc cf-turnstile trong HTML — phần lớn request không tốn lượt giải nào.
Hướng dẫn liên quan
- Đa dạng hoá nguồn proxy khi crawl dữ liệu học thuật
- Chất lượng proxy ảnh hưởng thế nào đến tỷ lệ giải CAPTCHA
Rút ngắn thời gian review tài liệu — lấy API key CaptchaAI và tự động hoá việc thu thập dữ liệu học thuật.