使用requests库爬取网页时<tr>起始标签缺失导致数据提取失败
解决缺失
<tr>起始标签的表格行提取问题 页面返回的HTML存在不规范情况:<tbody>下直接是<td>元素,仅存在</tr>结束标签,导致依赖严格XML规范的lxml解析器无法识别表格行。以下是三种可行解决方案:
方案1:预处理HTML补全<tr>标签
通过正则表达式在每个行块前插入缺失的<tr>起始标签,再用lxml解析:
from bs4 import BeautifulSoup import requests import re url = "https://companiesmarketcap.com/dow-jones/largest-companies-by-market-cap/" data = requests.get(url).text # 正则匹配从<td>开头到</tr>的完整行块,补全<tr>标签 processed_html = re.sub(r'(<td[^>]+>.*?</tr>)', r'<tr>\1', data, flags=re.DOTALL) soup = BeautifulSoup(processed_html, "lxml") table = soup.find("table") rows = table.find_all("tr") # 测试输出行内容 for row in rows: print([cell.get_text(strip=True) for cell in row.find_all("td")])
方案2:换用容错性更强的HTML解析器
BeautifulSoup的html.parser基于HTML5规范,对不规范HTML的容错处理更好,会自动补全缺失的<tr>标签:
from bs4 import BeautifulSoup import requests url = "https://companiesmarketcap.com/dow-jones/largest-companies-by-market-cap/" data = requests.get(url).text # 使用html.parser替代lxml soup = BeautifulSoup(data, "html.parser") table = soup.find("table") rows = table.find_all("tr") # 测试输出行内容 for row in rows: cells = row.find_all("td") if cells: print([cell.get_text(strip=True) for cell in cells])
方案3:直接按列数分组<td>元素
观察目标页面每行固定有8个<td>,可以直接抓取所有<td>,再按列数分组得到行数据:
from bs4 import BeautifulSoup import requests url = "https://companiesmarketcap.com/dow-jones/largest-companies-by-market-cap/" data = requests.get(url).text soup = BeautifulSoup(data, "lxml") table = soup.find("table") all_cells = table.find_all("td") # 每行固定8个单元格,按此分组 row_columns = 8 rows = [all_cells[i:i+row_columns] for i in range(0, len(all_cells), row_columns)] # 测试输出行内容 for row in rows: print([cell.get_text(strip=True) for cell in row])
方法对比
- 方案1:可控性强,但正则依赖HTML结构,页面结构变化时需调整表达式。
- 方案2:实现最简单,解析器自动处理不规范标签,适合大多数场景。
- 方案3:无需依赖解析器对标签的补全逻辑,只要列数固定就稳定可靠。
内容的提问来源于stack exchange,提问作者SnowHana
相关产品推荐
相关产品推荐

