使用BeautifulSoup解析HTML爬取比赛数据时出现AttributeError报错求助
问题原因及解决方案
报错的直接原因
你遇到的AttributeError: 'NoneType' object has no attribute 'find'错误,是因为代码里table = soup.find_all("table", {"class": "tabulkaquick"})[0].find('table')执行后返回了None:该页面的tabulkaquick类表格本身就是存储比赛数据的外层表格,内部没有嵌套的子table,所以find('table')找不到元素返回空值,后续调用find方法就会报错。
同时你写的DOM遍历逻辑完全不符合HTML表格的常规结构:正确的表格结构是table > tr > td,你写的table.find('td').find_all('tr')是在td里找tr,逻辑完全颠倒,就算前面拿到了正确的table也会报错。
其他隐藏错误
除了上述报错之外,你的代码还有多个逻辑错误:
- main.py中读取单元格属性的写法错误:不存在
cols[0].datetime、cols[3].int这类属性,正确写法是先取text属性拿到单元格文本,再做类型转换 - match.py中类型转换的写法错误:
host(str)是错误语法,将变量转字符串应该写str(host),同理int、float转换写法全部错误 - match.py的
__repr__方法写了多个return,第一个return执行后后面的代码全部不会生效,无法返回完整的比赛信息 - 类型转换没有做异常处理,遇到空单元格或者格式不符的内容会直接崩溃
修正后的代码
main.py
import urllib.request from bs4 import BeautifulSoup from match import Match matches= [] # 请求页面 url = "https://www.vitisport.cz/index.php?clanek=quicktips&sekce=fotbal&lang=pl" source = urllib.request.urlopen(url).read() soup = BeautifulSoup(source, 'html.parser') # 直接拿到目标表格 table = soup.find("table", {"class": "tabulkaquick"}) # 直接找表格下的所有行,可通过[1:]跳过表头行 rows = table.find_all('tr') for row in rows: cols = row.find_all("td") # 过滤掉列数不足的无效行 if len(cols) <7: continue try: matches.append(Match( cols[0].text.strip(), cols[1].text.strip(), cols[2].text.strip(), cols[3].text.strip(), cols[4].text.strip(), cols[5].text.strip(), cols[6].text.strip() )) except Exception as e: # 打印解析失败的行,不中断整个程序 print(f"解析行失败:{e}") continue # 写入文件 with open('matches_list.txt','w', encoding='utf-8') as f: for match in matches: print(match) f.write(f"{match.date},{match.host},{match.guest},{match.goals1st},{match.goals2nd},{match.type},{match.index}\n")
match.py
from datetime import datetime class Match: def __init__(self, date, host, guest, goals1st, goals2nd, type, index): self.date = datetime.strptime(date, '%d.%m.%Y') self.host = str(host) self.guest = str(guest) self.goals1st = int(goals1st) if goals1st.isdigit() else 0 self.goals2nd = int(goals2nd) if goals2nd.isdigit() else 0 self.type = str(type) self.index = float(index.replace(',','.')) if index else 0.0 def __repr__(self): # 拼接所有属性返回 return f"Match(date={self.date}, host={self.host}, guest={self.guest}, goals1st={self.goals1st}, goals2nd={self.goals2nd}, type={self.type}, index={self.index})"
内容的提问来源于stack exchange,提问作者kjakubk
相关产品推荐
相关产品推荐

