使用Python从网页获取链接:比Selenium更优的替代方案
提取网页中所有PDF链接的优化方案
听起来你遇到的问题很常见——很多网站的PDF链接可能藏在动态加载的内容里,或者你的初始代码没处理好相对URL、特殊属性这类细节。下面给你两个针对性的优化方案,应该能帮你拿到全部PDF链接:
方案1:针对静态渲染页面的增强版爬取(Requests + BeautifulSoup)
如果目标页面的PDF链接是静态HTML里的(只是你之前没找全),可以用这个方案,重点处理相对链接和多属性匹配:
import requests from bs4 import BeautifulSoup from urllib.parse import urljoin # 目标URL base_url = "http://stock.walmart.com/investors/financial-information/annual-reports-and-proxies/default.aspx" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" } # 获取页面内容 response = requests.get(base_url, headers=headers) response.raise_for_status() soup = BeautifulSoup(response.text, "html.parser") # 提取所有PDF链接:匹配a标签的href,以及可能的data-url等存储链接的属性 pdf_links = [] for a_tag in soup.find_all("a"): # 检查href属性 href = a_tag.get("href") if href and href.endswith(".pdf"): # 把相对链接转为绝对链接 absolute_url = urljoin(base_url, href) pdf_links.append(absolute_url) # 检查其他可能存链接的属性,比如data-url data_url = a_tag.get("data-url") if data_url and data_url.endswith(".pdf"): absolute_url = urljoin(base_url, data_url) pdf_links.append(absolute_url) # 去重并打印结果 unique_pdf_links = list(set(pdf_links)) for link in unique_pdf_links: print(link)
关键改进点:
- 加入了
User-Agent请求头,避免被网站识别为爬虫而返回不完整内容 - 用
urljoin自动处理相对链接转绝对链接,不会漏掉那些以/开头的链接 - 同时检查
href和data-url这类常见的存储链接的属性,覆盖更多隐藏PDF的场景 - 最后对链接去重,避免重复提取
方案2:针对动态加载页面的爬取(Playwright)
如果目标页面的PDF链接是通过JavaScript动态渲染的(比如点击加载更多、AJAX异步获取),静态爬取就拿不到,这时候用Playwright模拟真实浏览器加载页面是最优解:
首先安装Playwright:
pip install playwright playwright install chrome
然后编写代码:
from playwright.sync_api import sync_playwright from urllib.parse import urljoin base_url = "http://stock.walmart.com/investors/financial-information/annual-reports-and-proxies/default.aspx" with sync_playwright() as p: # 启动Chrome浏览器,设置无头模式(可选,去掉headless=False可以看到浏览器窗口) browser = p.chromium.launch(headless=True) page = browser.new_page(user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36") # 加载页面,等待所有网络请求完成 page.goto(base_url, wait_until="networkidle") # 提取所有PDF链接:包括静态和动态渲染的 pdf_links = [] # 获取所有a标签的href属性 hrefs = page.eval_on_selector_all("a", "elements => elements.map(el => el.href)") for href in hrefs: if href.endswith(".pdf"): pdf_links.append(href) # 同样检查data-url属性 data_urls = page.eval_on_selector_all("a[data-url]", "elements => elements.map(el => el.dataset.url)") for data_url in data_urls: if data_url.endswith(".pdf"): absolute_url = urljoin(base_url, data_url) pdf_links.append(absolute_url) # 去重并打印 unique_pdf_links = list(set(pdf_links)) for link in unique_pdf_links: print(link) browser.close()
优势:
- 完全模拟真实浏览器的渲染过程,能获取到JavaScript动态生成的所有内容
wait_until="networkidle"确保页面所有资源加载完成,不会漏掉延迟加载的PDF链接- 可以轻松扩展处理分页、点击加载更多等交互(比如调用
page.click()触发加载)
额外注意事项
- 有些网站会有反爬机制,如果你遇到403或被限制,可以尝试添加代理、增加请求间隔时间
- 可以对提取到的链接做有效性验证(比如发送HEAD请求检查状态码是否为200)
- 如果页面有多个分页,需要遍历所有分页URL重复提取逻辑
内容的提问来源于stack exchange,提问作者Catazza
相关产品推荐
相关产品推荐

