Kivy Buildozer打包后aiohttp异步请求失效致APP崩溃求助
问题原因及解决方法
1. 缺少Android网络权限
- 原因:Buildozer默认未配置INTERNET权限,导致APP无法发起网络请求,直接造成爬取失败。
- 解决:打开
buildozer.spec文件,添加权限配置:
保存后重新打包APK。android.permissions = INTERNET
2. Asyncio事件循环适配问题
- 原因:Android的Python环境(如python-for-android)对asyncio默认事件循环支持有限,再加上Kivy主线程与异步任务调度冲突,导致异步代码无法正常执行。
- 解决:
- 在APP启动时手动指定事件循环,同时用Kivy的
mainthread装饰器处理UI更新:import asyncio import sys from kivy.clock import mainthread # 适配Android环境的事件循环 if sys.platform == 'android': asyncio.set_event_loop(asyncio.new_event_loop()) # 异步任务获取数据后,必须用mainthread装饰器才能更新UI @mainthread def update_ui(parsed_data): # 编写更新UI的逻辑 pass async def fetch_data(): try: async with aiohttp.ClientSession() as session: async with session.get(url, params=querystring, headers=headers) as response: html = await response.text() soup = BeautifulSoup(html, 'html.parser') parsed_data = # 你的数据解析逻辑 update_ui(parsed_data) except Exception as e: print(f"爬取出错:{str(e)}") - 避免在Kivy的UI回调里直接阻塞主线程,用
asyncio.create_task()启动异步任务,而非asyncio.run()。
- 在APP启动时手动指定事件循环,同时用Kivy的
3. Aiohttp依赖打包不全
- 原因:Buildozer打包时未自动包含aiohttp的所有依赖(如chardet、multidict),运行时找不到对应模块,导致请求代码崩溃。
- 解决:
- 在
buildozer.spec的requirements中明确列出所有需要的依赖:requirements = python3,kivy,aiohttp,beautifulsoup4,chardet,multidict,yarl - 清理缓存后重新打包:
buildozer android clean buildozer android debug deploy run
- 在
4. 目标网站反爬拦截
- 原因:打包后的APP使用Python默认的User-Agent,极易被目标网站识别为爬虫,返回空页面或错误响应,导致无法解析出有效数据。
- 解决:
- 在请求headers中设置模拟移动端浏览器的UA,示例:
headers = { 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36' } - 对比PC端浏览器的请求头,补充必要参数(如Cookie、Referer),确保请求特征与正常浏览一致。
- 在请求headers中设置模拟移动端浏览器的UA,示例:
5. 未处理异步异常与数据校验
- 原因:异步请求过程中出现网络超时、连接失败等异常时,代码未捕获处理,导致任务直接终止无数据返回;后续计算时未校验数据有效性,触发除零错误。
- 解决:
- 给异步爬取函数添加异常捕获:
async def fetch_data(): try: async with aiohttp.ClientSession() as session: async with session.get(url, params=querystring, headers=headers, timeout=10) as response: if response.status != 200: print(f"请求失败,状态码:{response.status}") return None html = await response.text() soup = BeautifulSoup(html, 'html.parser') # 数据解析逻辑 return parsed_data except Exception as e: print(f"爬取异常:{str(e)}") return None - 计算前先校验数据有效性:
async def on_calculate_button_click(): # 启动异步任务 data = await asyncio.create_task(fetch_data()) if not data or data.get('target_value', 1) == 0: # 提示用户数据获取失败或无效 return # 执行正常计算逻辑
- 给异步爬取函数添加异常捕获:
内容的提问来源于stack exchange,提问作者MECRA YAVCIN
相关产品推荐
相关产品推荐

