標簽純文本的正確姿勢
爬取網頁數學題,HTML 中包含大量 (\xa0) 導致直接 soup.p 獲取亂碼,多次 prettify().replace() 後轉碼仍報錯 'str' object has no attribute 'string'。
new_soup = BeautifulSoup(soup.prettify()...) 將已解析樹序列化為字符串再解析,極易引入編碼問題且效率極低。soup.p 返回 Tag 對象,Tag.string 僅在標簽**僅包含單一 NavigableString** 時有效;若含子標簽(如 <span>)則返回 None。\xa0,而非在序列化後替換。from bs4 import BeautifulSoup
# 1. 原始 HTML 直接解析(requests 已自動處理編碼)
soup = BeautifulSoup(html_content, 'html.parser') # 或 'lxml' 更快
# 2. 定位目標 標簽
p_tag = soup.find('p') # 或 soup.select_one('p')
# 3. 獲取「可見文本」—— 自動遞歸提取所有子節點文本並拼接
raw_text = p_tag.get_text(strip=True) # strip=True 去除首尾空白
# 4. 清洗特殊空白字符(\xa0, \u3000 等)
clean_text = raw_text.replace('\xa0', ' ').replace('\u3000', ' ')
print(clean_text)
# 輸出:如圖所示,圓錐 SO 的軸截面 △SAB 是邊長為 4 的正三角形,M為母線 SB的中點,過直線 AM 作平面 β ⊥ 面 SAB ,設 β 與圓錐側面的交線為橢圓 C,則橢圓 C 的短半軸 為( )
若需保留 <span> 等內聯標簽的語義(如公式、強調),可遞歸遍歷:
def extract_rich_text(tag):
parts = []
for child in tag.children:
if isinstance(child, str):
parts.append(child.replace('\xa0', ' '))
elif child.name == 'span':
# 可根據 class/style 判斷是否為公式、強調等
parts.append(f"[{extract_rich_text(child)}]")
else:
parts.append(extract_rich_text(child))
return ''.join(parts)
rich = extract_rich_text(p_tag)
get_text() / .strings 生成器,不要用 .string。'lxml'(需安裝),容錯性強、速度快。requests 並設置 response.encoding = response.apparent_encoding 解決編碼自動識別。