分页页面PDF链接截图获取问题及技术方案咨询
问题解答
1. 为什么requests+BeautifulSoup能拿到所有链接,Selenium却不行?
核心差异在于页面渲染逻辑和AJAX的作用:
- requests是直接向服务器发起HTTP请求,拿到的是服务器返回的完整HTML源码——这个页面的服务器大概率把所有864个PDF链接提前嵌入到了返回的HTML里,所以BeautifulSoup直接解析就能获取全量内容。
- Selenium是模拟真实浏览器加载页面,而该页面的分页采用了AJAX动态加载机制:初始加载时,浏览器只渲染第一页的内容,剩余分页的数据不会自动加载。只有当你点击分页按钮时,浏览器才会在不刷新整个页面的前提下,偷偷发送AJAX请求到服务器获取对应页的数据,再通过JavaScript把新内容渲染到页面中。此时你直接用Selenium查找后续分页的元素,这些元素还未被添加到页面的DOM(文档对象模型)里,自然会抛出
NoSuchElementException。
简单总结:requests拿的是服务器给出的「全量数据包」,Selenium拿的是浏览器「逐步加载的内容片段」。
2. 除点击分页外的通用解决方案
推荐两种更高效的思路:
方案一:复用requests的全量数据生成本地页面
既然requests已经能获取所有PDF链接,你可以把这些链接整理成一个简易HTML页面,保存为本地文件后用Selenium打开。此时所有元素都在DOM中,直接定位截图即可,完全不用处理分页逻辑。
示例代码思路:
import requests from bs4 import BeautifulSoup from selenium import webdriver from selenium.webdriver.common.by import By # 用requests抓取所有PDF链接 url = "https://aplng.com.au/document-library/" response = requests.get(url) soup = BeautifulSoup(response.text, "html.parser") pdf_links = soup.find_all("a", href=lambda x: x and x.endswith(".pdf")) # 生成包含所有链接的本地HTML html_content = """ <!DOCTYPE html> <html> <body> """ for link in pdf_links: html_content += f'<div class="pdf-item"><a href="{link["href"]}">{link.text.strip()}</a></div>\n' html_content += """ </body> </html> """ with open("all_pdfs.html", "w", encoding="utf-8") as f: f.write(html_content) # Selenium打开本地页面并截图 driver = webdriver.Chrome() driver.get("file:///你的本地文件路径/all_pdfs.html") # 定位所有PDF链接区域并逐个截图 pdf_elements = driver.find_elements(By.CLASS_NAME, "pdf-item") for idx, elem in enumerate(pdf_elements): elem.screenshot(f"pdf_area_{idx}.png") driver.quit()
方案二:直接调用页面的API接口
打开浏览器开发者工具(按F12),切换到「网络」标签,点击分页按钮观察浏览器发送的请求——你会发现一个专门加载文档列表的API(通常是GET请求,参数包含页码、每页数量)。直接请求这个API就能拿到所有分页的JSON数据,再根据数据生成页面或直接定位元素截图,比模拟点击效率高得多。
3. 若必须点击分页,如何规避异常?
如果一定要模拟分页点击,重点解决元素等待和分页终止判断的问题:
- 用显式等待替代固定延迟:不要用
time.sleep()这种生硬的等待,改用WebDriverWait配合expected_conditions等待元素加载完成,比如等待下一页按钮可见、等待当前页的PDF元素出现。
示例代码:from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By wait = WebDriverWait(driver, 10) # 等待下一页按钮可见 next_btn = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "你的下一页按钮选择器"))) next_btn.click() # 等待当前页的PDF元素加载完成 wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "你的PDF链接选择器"))) - 判断分页终止条件:当页面没有下一页按钮(比如按钮变灰、消失)时停止点击。可以用
try-except捕获NoSuchElementException来判断是否到达最后一页。 - 处理元素交互问题:如果分页按钮被页面元素遮挡,用
driver.execute_script("arguments[0].scrollIntoView();", next_btn)滚动到按钮位置再点击;如果点击无反应,尝试用JS执行点击:driver.execute_script("arguments[0].click();", next_btn)。 - 添加异常重试机制:偶尔会因网络波动导致元素加载失败,给点击和定位逻辑加重试次数,比如循环3次尝试点击下一页。
内容的提问来源于stack exchange,提问作者Fariz Awi
相关产品推荐
相关产品推荐

