Xây dựng công cụ so sánh giá thuốc có nghĩa là thu thập dữ liệu về giá từ nhiều cổng hiệu thuốc, cơ sở dữ liệu về giá thuốc và công thức bảo hiểm. Nhiều nguồn trong số này bảo vệ các trang định giá của họ bằng CAPTCHA — đặc biệt là reCAPTCHA v2 trên các biểu mẫu tìm kiếm và trang kết quả. Dưới đây là cách xử lý chúng.
Nơi CAPTCHA xuất hiện trong cổng hiệu thuốc
| Loại trang | CAPTCHA phổ biến | Trình kích hoạt |
|---|---|---|
| Mẫu tra cứu thuốc | reCAPTCHA v2 | Mỗi truy vấn tìm kiếm |
| Trang kết quả giá | Cloudflare Turnstile | Truy cập tự động bị nghi ngờ |
| Định vị nhà thuốc | reCAPTCHA v2 | Truy vấn dựa trên vị trí |
| Tra cứu phiếu giảm giá | CAPTCHA hình ảnh | Trước khi hiển thị mã giảm giá |
| Danh mục bảo hiểm | reCAPTCHA v2 | Đăng nhậpCổng /search |
Quy trình làm việc cơ bản
import requests
import time
session = requests.Session()
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
})
def solve_recaptcha(site_key, page_url):
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": site_key,
"pageurl": page_url,
"json": 1
})
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(3)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY",
"action": "get",
"id": task_id,
"json": 1
})
data = result.json()
if data["status"] == 1:
return data["request"]
raise TimeoutError("Solve timed out")
def search_drug_prices(drug_name, zipcode):
search_url = "https://pharmacy.example.com/search"
# Load the search page to get the site key
page = session.get(search_url)
# Extract reCAPTCHA site key
import re
match = re.search(r'data-sitekey="([^"]+)"', page.text)
site_key = match.group(1)
# Solve the CAPTCHA
token = solve_recaptcha(site_key, search_url)
# Submit the search with token
results = session.post(search_url, data={
"drug": drug_name,
"zip": zipcode,
"g-recaptcha-response": token
})
return parse_prices(results.text)
So sánh nhiều hiệu thuốc
So sánh giá trên nhiều nguồn:
PHARMACY_SOURCES = [
{
"name": "PharmacyA",
"url": "https://pharmacya.example.com/pricing",
"captcha_type": "recaptcha_v2"
},
{
"name": "PharmacyB",
"url": "https://pharmacyb.example.com/drugs",
"captcha_type": "turnstile"
},
{
"name": "PharmacyC",
"url": "https://pharmacyc.example.com/search",
"captcha_type": "image"
}
]
def compare_drug_price(drug_name, zipcode):
results = []
for source in PHARMACY_SOURCES:
try:
prices = fetch_prices(
source["url"],
source["captcha_type"],
drug_name,
zipcode
)
results.append({
"source": source["name"],
"prices": prices,
"status": "success"
})
except Exception as e:
results.append({
"source": source["name"],
"error": str(e),
"status": "failed"
})
return sorted(results, key=lambda r: r.get("prices", {}).get("lowest", float("inf")))
Xử lý các loại CAPTCHA khác nhau
Cổng dược phẩm sử dụng nhiều nhà cung cấp CAPTCHA khác nhau:
def fetch_prices(url, captcha_type, drug_name, zipcode):
page = session.get(url)
if captcha_type == "recaptcha_v2":
import re
match = re.search(r'data-sitekey="([^"]+)"', page.text)
token = solve_recaptcha(match.group(1), url)
field_name = "g-recaptcha-response"
elif captcha_type == "turnstile":
import re
match = re.search(r'data-sitekey="(0x[^"]+)"', page.text)
token = solve_turnstile(match.group(1), url)
field_name = "cf-turnstile-response"
elif captcha_type == "image":
img_data = extract_captcha_image(page.text)
token = solve_image_captcha(img_data)
field_name = "captcha"
return session.post(url, data={
"drug": drug_name,
"zip": zipcode,
field_name: token
})
Quản lý phiên cho tìm kiếm lặp lại
So sánh giá thuốc yêu cầu nhiều tìm kiếm. Quản lý các phiên để giảm thiểu việc gặp phải CAPTCHA:
class PharmacySession:
def __init__(self, base_url):
self.session = requests.Session()
self.base_url = base_url
self.searches_since_captcha = 0
def search(self, drug_name, zipcode):
result = self.session.post(f"{self.base_url}/search", data={
"drug": drug_name,
"zip": zipcode
})
if self.is_captcha_page(result.text):
token = self.solve_page_captcha(result.text)
result = self.session.post(f"{self.base_url}/search", data={
"drug": drug_name,
"zip": zipcode,
"g-recaptcha-response": token
})
self.searches_since_captcha = 0
else:
self.searches_since_captcha += 1
return result
def is_captcha_page(self, html):
return "g-recaptcha" in html or "cf-turnstile" in html
def solve_page_captcha(self, html):
import re
match = re.search(r'data-sitekey="([^"]+)"', html)
return solve_recaptcha(match.group(1), self.base_url)
Triển khai JavaScript
async function comparePharmacyPrices(drugName, zipCode, sources) {
const results = await Promise.all(
sources.map(async (source) => {
try {
const price = await fetchDrugPrice(source, drugName, zipCode);
return { source: source.name, price, status: 'success' };
} catch (error) {
return { source: source.name, error: error.message, status: 'failed' };
}
})
);
return results
.filter(r => r.status === 'success')
.sort((a, b) => a.price - b.price);
}
async function fetchDrugPrice(source, drugName, zipCode) {
// Solve CAPTCHA for this source
const token = await solveCaptcha(source.siteKey, source.url);
const response = await fetch(source.url, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
drug: drugName,
zip: zipCode,
'g-recaptcha-response': token
})
});
return parsePrice(await response.text());
}
Cân nhắc giới hạn tỷ lệ
Cổng dược phẩm giám sát chặt chẽ các mẫu truy cập:
| Chiến lược | Thực hiện |
|---|---|
| Yêu cầu không gian | 5–10 giây giữa các lần tìm kiếm |
| Xoay phiên | Phiên mới cứ sau 20–30 truy vấn |
| Thay đổi mẫu tìm kiếm | Đừng tìm kiếm cùng một loại thuốc nhiều lần |
| Sử dụng đa dạng nguồn yêu cầu | IP của trung tâm dữ liệu kích hoạt nhiều CAPTCHA hơn |
Khắc phục sự cố
| Vấn đề | Nguyên nhân | Cách xử lý |
|---|---|---|
| CAPTCHA trên mọi tìm kiếm | Phiên không tồn tại cookie | Sử dụng requests.Session() và duy trì cookie |
| Giá không tải sau CAPTCHA | Thiếu mã thông báo CSRF | Trích xuất và bao gồm các trường biểu mẫu ẩn |
| Khối trang web sau nhiều lần tìm kiếm | Giới hạn tỷ lệ | Thêm độ trễ giữa các yêu cầu |
| Giá khác với trình duyệt | Thiếu cookie hoặc tiêu đề phiên | Khớp chính xác tiêu đề trình duyệt |
Câu hỏi thường gặp
Tôi có thể so sánh đồng thời bao nhiêu nguồn dược phẩm?
CaptchaAI xử lý việc giải quyết song song. Bạn có thể giải CAPTCHA cho nhiều cổng hiệu thuốc cùng một lúc. Giới hạn thực tế phụ thuộc vào số dư CaptchaAI của bạn và giới hạn tỷ lệ của mỗi cổng.
Cổng thông tin hiệu thuốc có thường xuyên thay đổi loại CAPTCHA không?
Một số cổng cập nhật việc triển khai CAPTCHA theo định kỳ. Theo dõi các thay đổi bằng cách kiểm tra xem bản trích xuất của bạn có còn tìm thấy khóa trang hay không. CaptchaAI hỗ trợ tất cả các loại CAPTCHA chính, do đó, việc chuyển đổi nhà cung cấp không yêu cầu bạn phải thay đổi phương pháp giải.
Có sự khác biệt giữa cổng thông tin định giá thuốc gốc và thuốc gốc không?
Việc xử lý CAPTCHA cũng tương tự. Cơ sở dữ liệu thuốc gốc có thể sử dụng CAPTCHA hình ảnh đơn giản hơn, trong khi các cổng thông tin hiệu thuốc có thương hiệu có xu hướng sử dụng reCAPTCHA v2 hoặc Turnstile.
bài viết liên quan
- Cách giải quyết cuộc gọi lại Recaptcha V2 bằng Api
- Xử lý cửa quay Recaptcha V2 trên cùng một trang web
- Cơ chế gọi lại Recaptcha V2
Các bước tiếp theo
Xây dựng công cụ so sánh giá hiệu thuốc của bạn —lấy khóa API CaptchaAI của bạnvà xử lý CAPTCHA trên tất cả các nguồn dược phẩm.