为何用urllib+BeautifulSoup无法获取https://retty.me完整HTML?
问题分析与解决方案
嘿,我来帮你排查下问题!你遇到的情况其实很常见,核心原因大概率是网页内容动态渲染导致的,咱们一步步拆解:
为什么只拿到一个链接?
你用urlopen获取的是服务器返回的初始静态HTML源码,但retty.me这类现代网站很多内容是通过JavaScript动态生成的——也就是说,那些你在浏览器里看到的大量链接,是页面加载完成后,JS脚本才把它们插入到页面中的,初始源码里根本没有这些内容。所以你打印页面只能看到一个链接,BeautifulSoup自然也找不到其他的。
解决办法
1. 用工具模拟浏览器渲染(最直接的方案)
可以用selenium或playwright这类工具,它们能像真实浏览器一样加载页面、执行JS,等页面完全渲染后再获取完整的HTML。这里以selenium为例:
首先安装依赖:
pip install selenium
然后下载对应浏览器的驱动(比如ChromeDriver,要和你的浏览器版本匹配),接着修改代码:
from selenium import webdriver from selenium.webdriver.chrome.service import Service from bs4 import BeautifulSoup import time # 替换成你的ChromeDriver路径 service = Service('/path/to/your/chromedriver') driver = webdriver.Chrome(service=service) # 打开目标网站 driver.get('https://retty.me') # 等待3秒让JS完成渲染(也可以用更智能的显式等待,比如等待某个元素加载完成) time.sleep(3) # 获取渲染后的完整页面源码 html = driver.page_source soup = BeautifulSoup(html, 'lxml') # 提取所有带href的链接 all_links = soup.find_all('a', href=True) for link in all_links: print(link['href']) # 记得关闭浏览器 driver.quit()
2. 直接请求网站的API接口(更高效的方案)
有些动态网站会通过AJAX请求从后端拉取数据,你可以通过浏览器开发者工具找接口:
- 打开浏览器F12,切换到「网络」标签
- 刷新页面,筛选「XHR」或「Fetch」类型的请求
- 查看每个请求的响应内容,找到包含链接数据的接口
- 用
requests库直接请求这个接口,就能拿到结构化的链接数据,不需要处理HTML
3. 先检查请求头是否被限制
有些网站会识别爬虫请求,返回不完整内容。你可以给请求添加模拟浏览器的User-Agent头试试,用urllib的话代码如下:
from urllib.request import urlopen, Request from bs4 import BeautifulSoup # 模拟浏览器的请求头 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' } # 构造带请求头的请求 req = Request('https://retty.me', headers=headers) html = urlopen(req) soup = BeautifulSoup(html, 'lxml') # 再次提取链接 links = soup.find_all('a', href=True) for link in links: print(link['href'])
不过这个方法只能解决请求头被拦截的问题,没法解决动态渲染的核心问题,但可以先排除这个可能性。
内容的提问来源于stack exchange,提问作者dip deb
相关产品推荐
相关产品推荐

