Python爬虫翻页爬取网页时触发AttributeError异常求助
项目背景
正在开发用于练习Python技能的小项目,目标是爬取彩票游戏相关数据并分析规律,核心需求如下:
- 爬取历史开奖号码及对应的开奖日期
- 将爬取到的数据存储为txt或CSV格式文件
- 分析存储的数据,生成合理的预测结果
初始实现版本
最初方案是先将HTML文件下载到本地,再读取本地文件做数据解析,实现代码如下:
from bs4 import BeautifulSoup # 初始化soup和html数据源 with open('lotto_test.html', 'r') as html_file: content = html_file.read() soup = BeautifulSoup(content, 'lxml') # 指定数据写入文件 file = open('Numbers.txt', 'w') # 查找对应class下的开奖号码,打印并写入文件 for ul in soup.find_all('ul', class_='resultsNums'): numbers = ul.text print(numbers) file.write(numbers) # 查找对应class下的开奖日期,打印并写入文件 for dates in soup.find_all('div', class_='resultsDrawDate'): dod = dates.text print(dod) file.write(dod) file.flush() file.close
该版本虽然输出数据格式不够规范,但已经可以实现基础爬取需求。
分页爬取调整版本
为了获取累计1年的大量历史数据,调整方案为程序直接从目标网页逐页爬取,调整后代码如下:
from requests_html import HTMLSession from bs4 import BeautifulSoup s = HTMLSession() url = 'https://www.lotterypost.com/game/98/results' def get_data(url): r = s.get(url) r.html.render(sleep=1) soup = BeautifulSoup(r.html.html, 'html.parser') return soup def next_page(soup): page = soup.find('div', {"class":"CSR-Paging"}) if not page.find('span', {"class":"CSR-PrevNext"}): url = "https://www.lotterypost.com/game/98/results" + str(page.find('div', {'class':'CSR-Paging'}).find('a')['href']) return url else: return while True: soup = get_data(url) url = next_page(soup) if not url: break print(url)
运行上述代码后抛出如下报错:
Traceback (most recent call last): File "/Volumes/Local NAS/Cross Platform Files/Lotto Calc/scraper.py", line 23, in <module> url = next_page(soup) File "/Volumes/Local NAS/Cross Platform Files/Lotto Calc/scraper.py", line 15, in next_page if not page.find('span', {"class":"CSR-PrevNext"}): AttributeError: 'NoneType' object has no attribute 'find'
报错原因与修复方案
核心报错原因
报错和Python内置方法无关,.find()是BeautifulSoup标签对象的方法,触发AttributeError: 'NoneType' object has no attribute 'find'的直接原因是:page = soup.find('div', {"class":"CSR-Paging"}) 这行代码没有匹配到class为CSR-Paging的div元素,返回了空值None,后续直接对None调用.find()方法自然会报错。
具体问题点
请求被站点反爬拦截
直接用默认请求头发起访问,站点识别到爬虫特征后,返回的不是正常的开奖结果页面,可能是验证码页、访问拦截页,这类页面自然不存在分页组件。可以在get_data函数里加一行print(soup.prettify())打印返回的页面内容,即可确认是否被拦截。修复时需要给请求添加正常的User-Agent等请求头,模拟浏览器行为。分页逻辑存在错误
就算成功拿到正常页面,原有分页逻辑也存在缺陷:
- 元素判断逻辑错误:第一页不存在“上一页”按钮,最后一页不存在“下一页”按钮,原有判断逻辑没有区分两个按钮的类名差异,会导致翻页提前终止或者死循环。
- URL拼接逻辑错误:分页a标签的href属性本身是站点相对路径或完整路径,硬拼固定前缀会生成错误的跳转地址。
- 缺少空值判断:查找DOM元素后没有先判断是否拿到了有效对象,直接调用方法很容易触发空值报错。
额外提醒:彩票开奖号码是完全随机的独立事件,不存在可以通过历史数据预测未来结果的规律,该项目仅适合作为Python爬虫练习使用。
内容的提问来源于stack exchange,提问作者Doctor A

