BeautifulSoup报错'NavigableString'无find_all属性,网页爬取求助
问题根源
你遇到的AttributeError: 'NavigableString' object has no attribute 'find_all',是因为在遍历home_substititions.find('tbody')的子节点时,除了目标<tr>标签,还会混入空白文本节点(比如换行、空格)。这些文本节点在BeautifulSoup里属于NavigableString类型,根本没有find_all方法,自然会报错。
原来的循环for table in home_substititions.find('tbody'):会把tbody下的所有子节点都拿出来遍历,包括那些看不见的空白文本,当循环到这些文本节点时,调用table.find_all('tr')就触发了错误。
快速修复方案
最省心的办法是直接定位到tbody下的所有<tr>标签,跳过那些无关的文本节点。这样循环变量只会是合法的Tag对象,不会再出现类型错误。同时我也帮你修正了代码里的几个小问题:
import requests from bs4 import BeautifulSoup import uuid from datetime import timedelta link = 'https://rugby.statbunker.com/competitions/MatchDetails/World-Cup-2019/Japan-VS-Russia?comp_id=606&match_id=39737&date=20-Sep-2019' response = requests.get(link) html_loop = response.content soup_loop = BeautifulSoup(html_loop, 'html.parser') home_substititions = soup_loop.find('table', {'id': 'homeSubs'}) homeSubstitutionEvents = [] # 这里替换成你实际的game对象 game = {'gameTime': ...} # 直接获取tbody下的所有tr标签,避免遍历文本节点 for row in home_substititions.find('tbody').find_all('tr'): substitutionEvent = {} substitutionEvent['uuid'] = uuid.uuid1() # 一次性获取所有td,减少重复调用 tds = row.find_all('td') # 先检查td数量,防止索引越界报错 if len(tds) >= 5: substitutionEvent['playerIn'] = tds[2].text.strip() substitutionEvent['playerOut'] = tds[4].text.strip() time_text = tds[0].text.strip() time_part = time_text.split('`')[0] # 确保时间部分是数字再转换 if time_part.isdigit(): # 修正timedelta的写法,不需要.Timedelta substitutionEvent['subTime'] = game['gameTime'] + timedelta(minutes=int(time_part)) else: substitutionEvent['subTime'] = '' homeSubstitutionEvents.append(substitutionEvent)
另一种思路:过滤非标签节点
如果你一定要保留遍历tbody子节点的逻辑,可以在循环里先判断当前节点是不是Tag类型,跳过文本节点:
from bs4.element import Tag # ... 前面的代码不变 ... for node in home_substititions.find('tbody'): # 只处理Tag对象,跳过文本节点 if not isinstance(node, Tag): continue # 接下来再处理node(也就是原来的table变量) if node.find_all('tr'): # ... 你的原有逻辑 ...
这样也能避免触发AttributeError。
内容的提问来源于stack exchange,提问作者greenmeansgo
相关产品推荐
相关产品推荐

