使用Python提取href="#"网页中的PDF链接:AJAX POST请求未返回预期结果
解决AJAX动态加载PDF链接的自动化下载问题
看起来你卡在AJAX POST请求这一步了,这种动态加载的场景确实容易踩坑,我来给你几个实用的思路和代码示例:
1. 先搞清楚AJAX POST的真实请求细节
首先打开浏览器的开发者工具(F12),切换到Network标签,触发加载PDF链接的操作,找到对应的POST请求:
- 查看请求的Form Data或者Request Payload,确认参数是否正确
- 复制请求头(Headers)里的关键字段,比如
Cookie、User-Agent、X-Requested-With这些,这些往往是服务器验证身份的关键 - 检查响应的格式,是JSON还是HTML,确认你要的PDF链接藏在响应的哪个字段里
2. 换掉PhantomJS,改用Headless Chrome
PhantomJS早就停止维护了,对现代JS和AJAX的支持不如Chrome Headless稳定,换这个能解决不少兼容性问题。初始化代码示例:
from selenium import webdriver from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.add_argument("--headless=new") chrome_options.add_argument("--disable-gpu") driver = webdriver.Chrome(options=chrome_options)
3. 用显式等待替代直接查找元素
AJAX加载需要时间,直接调用find_elements可能会拿到空结果,用Selenium的显式等待确保元素加载完成:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # 等待最多10秒,直到包含PDF链接的元素出现 wait = WebDriverWait(driver, 10) pdf_links = wait.until(EC.presence_of_all_elements_located((By.XPATH, "//a[contains(@href, '.pdf')]"))) # 提取链接 for link in pdf_links: pdf_url = link.get_attribute("href") print(pdf_url)
4. 直接捕获AJAX响应内容
如果通过页面元素拿不到链接,可以用Selenium的DevTools API监听网络请求,直接获取POST响应:
# 开启网络请求监听 driver.execute_cdp_cmd("Network.enable", {}) # 定义回调函数捕获响应 def capture_response(response): request_id = response["requestId"] if response["response"]["url"].endswith("your-ajax-endpoint"): # 替换成你的AJAX接口URL body = driver.execute_cdp_cmd("Network.getResponseBody", {"requestId": request_id}) print(body["body"]) driver.add_cdp_listener("Network.responseReceived", capture_response) # 触发AJAX请求的操作(比如点击按钮) driver.find_element(By.ID, "load-pdf-btn").click()
5. 用requests替代wget下载PDF
拿到PDF链接后,用requests库下载可以带上必要的请求头,避免403禁止访问的问题:
import requests # 从Selenium获取当前会话的Cookie,转换成requests需要的格式 cookies = {cookie['name']: cookie['value'] for cookie in driver.get_cookies()} headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" } response = requests.get(pdf_url, headers=headers, cookies=cookies, stream=True) with open("downloaded.pdf", "wb") as f: for chunk in response.iter_content(chunk_size=1024): f.write(chunk)
记得最后关闭driver:driver.quit()
内容的提问来源于stack exchange,提问作者Alan
相关产品推荐
相关产品推荐

