| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- """
- 多源数据探头 — 测试各药品数据源的可用性
- """
- import asyncio
- import httpx
- import re
- from bs4 import BeautifulSoup
- HEADERS = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/125.0.0.0 Safari/537.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
- "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
- }
- async def probe(url, name, method="GET", json_data=None, timeout=15):
- """探测一个数据源"""
- try:
- async with httpx.AsyncClient(timeout=timeout, follow_redirects=True) as c:
- if method == "POST":
- resp = await c.post(url, headers=HEADERS, json=json_data)
- else:
- resp = await c.get(url, headers=HEADERS)
- size = len(resp.text)
- status = resp.status_code
- snippet = resp.text[:200].replace("\n", " ").strip()
- # 检查是否有验证码/反爬
- anticrawl = any(
- k in resp.text.lower()
- for k in ["captcha", "验证码", "滑块", "verify", "forbidden", "403", "blocked", "请滑动"]
- )
- flag = "⚠ 反爬" if anticrawl else "✅" if status == 200 else f"❌ {status}"
- has_drug = bool(re.search(r"阿莫西林|药品|批号|标准", resp.text)) if status == 200 else False
- print(f"{flag} {name}")
- print(f" URL: {url}")
- print(f" {status} | {size:,} bytes | 含药品信息: {has_drug}")
- print(f" {snippet}\n")
- return {"ok": status == 200 and not anticrawl, "size": size, "has_drug": has_drug}
- except Exception as e:
- print(f"❌ {name}: {str(e)[:100]}\n")
- return {"ok": False, "size": 0, "has_drug": False}
- async def main():
- print("═" * 60)
- print(" 数据源探测报告")
- print("═" * 60 + "\n")
- sources = [
- # 1. NMPA 公告列表(静态页面)
- ("NMPA 最新公告", "https://www.nmpa.gov.cn/xxgk/ggtg/index.html"),
- # 2. NMPA 药品查询 API(可能存在的 JSON 接口)
- ("NMPA 药品查询 API (试探)",
- "https://www.nmpa.gov.cn/datasearch/data/nmpa/search.json",
- "POST",
- {"category": "ps", "condition": "阿莫西林", "pageSize": 5, "pageNum": 1}),
- # 3. 药智网(公开信息)
- ("药智网-阿莫西林", "https://www.yaozh.com/product/103009.html"),
- # 4. 中国药典在线(公开)
- ("药典在线", "http://www.drugfuture.com/standard/"),
- # 5. 药智数据 API(公开试用)
- ("药智数据 search", "https://db.yaozh.com/drugcompatible/search"),
- # 6. 国家药品标准查询
- ("药品标准查询", "https://www.nifdc.org.cn/nifdc/xxgk/bzxx/index.html"),
- # 7. 丁香园用药助手
- ("丁香园用药助手", "https://drugs.dxy.cn/search/index.htm"),
- # 8. 药物在线(drugfuture)具体药品
- ("药物在线-阿莫西林", "http://www.drugfuture.com/standard/search.aspx?key=%B0%A2%C4%AA%CE%F7%C1%D6"),
- # 9. 百度百科(结构化药品信息)
- ("百度百科-阿莫西林", "https://baike.baidu.com/item/%E9%98%BF%E8%8E%AB%E8%A5%BF%E6%9E%97"),
- ]
- results = []
- for args in sources:
- name = args[0]
- url = args[1]
- method = args[2] if len(args) > 2 else "GET"
- json_data = args[3] if len(args) > 3 else None
- r = await probe(url, name, method, json_data)
- results.append((name, r))
- print("═" * 60)
- print(" 总结")
- print("═" * 60)
- ok_sources = [(n, r) for n, r in results if r["ok"] and r["has_drug"]]
- partial = [(n, r) for n, r in results if r["ok"] and not r["has_drug"]]
- failed = [(n, r) for n, r in results if not r["ok"]]
- print(f"\n✅ 可用(含药品数据): {len(ok_sources)}")
- for n, r in ok_sources:
- print(f" - {n} ({r['size']:,} bytes)")
- print(f"\n🟡 可访问但无药品数据: {len(partial)}")
- for n, r in partial:
- print(f" - {n} ({r['size']:,} bytes)")
- print(f"\n❌ 不可用: {len(failed)}")
- for n, r in failed:
- print(f" - {n}")
- print(f"\n推荐优先采集: ", end="")
- if ok_sources:
- print(", ".join(n for n, _ in ok_sources[:3]))
- else:
- print("无可用数据源,建议手动整理药典 PDF 或购买第三方 API")
- if __name__ == "__main__":
- asyncio.run(main())
|