You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python如何从动态加载PDF的URL下载文件并适配Chrome无头模式

问题描述

注意:本问题和Stack Overflow上其他同类问题存在明显差异。
原因是目标URL:https://webice.ongc.co.in/pay_adv?TRACKNO=8262#不会直接返回PDF文件,而是会发起多个后续请求,其中某一个请求的响应才是目标PDF文件。

需求是为URL的查询参数TRACKNO传入变量值,通过Python实现对应PDF文件的下载保存。
目前已通过Selenium实现功能,但开启Chrome浏览器无头模式后代码就会失效,需要代码能在无头模式下正常运行。现有代码如下:

import requests
from urllib3.exceptions import InsecureRequestWarning
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time

def extract_url(driver):
    advice_requests = driver.execute_script("var performance = window.performance || window.mozPerformance || window.msPerformance || window.webkitPerformance || {}; var network = performance.getEntries() || {}; return network;")
    print(advice_requests)
    for request in advice_requests:
        if(request.get('initiatorType',"") == 'object' and request.get('entryType',"") == 'resource'):
            link_split = request['name'].split('-')
            if(link_split[-1] == 'filedownload=X'):
                print("..... Successful")
                return request['name']
    print("..... Failed")

def save_advice(advice_url,tracking_num):
    requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
    response = requests.get(advice_url,verify=False)

    with open(f'{tracking_num}.pdf', 'wb') as f:
        f.write(response.content)

def get_payment_advice(tracking_nums):
    options = webdriver.ChromeOptions()
#   options.add_argument('headless')  # 无头模式下无法运行,因此注释
    driver = webdriver.Chrome(options=options)
    
    for num in tracking_nums:
        print(num,end=" ")
        driver.get(f'https://webice.ongc.co.in/pay_adv?TRACKNO={num}#')
        try:
            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'ls-highlight-domref')))
            time.sleep(0.1)
            advice_url = extract_url(driver)
            save_advice(advice_url,num)
        except:
            pass
    driver.quit()

get_payment_advice(['8262'])

现有逻辑是在extract_url函数中通过获取浏览器发起的所有网络调用,逐一解析筛选出正确的PDF请求地址,但该逻辑在无头模式下无法生效。
询问是否有更合理的实现方式,或者现有代码如何修复适配无头模式运行。


解决方案

失效原因

Chrome旧版无头模式(使用--headless参数)的浏览器行为和普通模式存在差异,资源加载的性能日志统计规则不一致,导致performance.getEntries()无法捕获到PDF文件的请求记录。

方案1:切换新版无头模式(最小代码改动)

Chrome 112及以上版本推出了新版无头模式,行为和普通Chrome完全一致,仅需修改无头模式配置参数即可:
将原代码中注释的无头模式配置替换为:

options.add_argument('--headless=new')
options.add_argument('--disable-gpu')
options.add_argument('--no-sandbox')

同时注意原代码最后一行存在语法错误,get_payment_advice['8262']要改为get_payment_advice(['8262']),修改后即可正常运行。

方案2:使用CDP监听网络请求(稳定性更高)

如果不想依赖performanceAPI,可以通过Selenium调用Chrome DevTools协议直接监听所有网络请求,不会出现漏抓的情况,代码可靠性更高:

import requests
from urllib3.exceptions import InsecureRequestWarning
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time

def save_advice(advice_url,tracking_num):
    requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
    response = requests.get(advice_url,verify=False)
    with open(f'{tracking_num}.pdf', 'wb') as f:
        f.write(response.content)

def get_payment_advice(tracking_nums):
    options = webdriver.ChromeOptions()
    options.add_argument('--headless=new')
    options.add_argument('--disable-gpu')
    options.add_argument('--no-sandbox')
    driver = webdriver.Chrome(options=options)
    # 启用网络监听
    driver.execute_cdp_cmd('Network.enable', {})
    for num in tracking_nums:
        print(num,end=" ")
        pdf_url = None
        # 注册请求拦截器捕获PDF地址
        def request_interceptor(request):
            nonlocal pdf_url
            if 'filedownload=X' in request['request']['url']:
                pdf_url = request['request']['url']
        driver.request_interceptor = request_interceptor
        driver.get(f'https://webice.ongc.co.in/pay_adv?TRACKNO={num}#')
        try:
            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'ls-highlight-domref')))
            # 预留足够时间捕获请求
            time.sleep(0.5)
            if pdf_url:
                print("..... Successful")
                save_advice(pdf_url,num)
            else:
                print("..... Failed")
        except Exception as e:
            print(f"..... Error: {str(e)}")
    driver.quit()

get_payment_advice(['8262'])

方案3:纯requests实现(运行效率更高)

如果不想依赖Selenium,可以逆向站点的请求流程,直接用requests模拟携带Cookie、请求头调用接口拿到PDF地址,运行效率更高。该方案需要先梳理站点的请求校验规则,适合请求逻辑固定的场景。


内容的提问来源于stack exchange,提问作者dracarys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 05:15:10