Discord卡牌价格爬虫Bot本地正常,部署服务器后返回空数组报错
问题排查:Discord Bot爬取Lorcana价格本地正常、服务器返回空数组
核心问题
本地Macbook Air(M3)运行时能正常获取span.btn-price元素的价格数据,但部署到PlyexNodes服务器后,soup.findAll('span', class_="btn-price")返回空数组,触发IndexError: list index out of range。
可能原因及解决办法
1. 请求头缺失被反爬拦截
服务器端直接用requests发起请求时,默认请求头无浏览器标识,易被网站反爬机制识别拦截,返回的HTML中没有价格元素。
解决办法:给请求添加模拟浏览器的请求头,重点配置User-Agent:
import requests from bs4 import BeautifulSoup import re # 模拟浏览器请求头 headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' } # 带请求头发起请求 r = requests.get('https://lorcanaplayer.com/lorcana-card-list/', headers=headers) # 检查请求状态码,正常应为200 print(r.status_code) soup = BeautifulSoup(r.text, 'html.parser') array = [item.get_text() for item in soup.findAll('span', class_="btn-price")] newArr = [] for i in array: pattern = re.compile(r'\-?\d+\.\d+') diffPrices = list(map(float, re.findall(pattern, i))) newArr.append(str(diffPrices))
2. 页面依赖JavaScript动态渲染
目标网站的价格数据可能通过JS动态加载,本地运行时间接触发了JS渲染能拿到完整内容;但服务器端用requests仅能获取静态HTML,无法加载动态生成的元素。
解决办法:使用支持JS渲染的工具(如Playwright)获取页面内容:
from playwright.sync_api import sync_playwright from bs4 import BeautifulSoup import re with sync_playwright() as p: # 无头模式启动浏览器 browser = p.chromium.launch(headless=True) page = browser.new_page() page.goto('https://lorcanaplayer.com/lorcana-card-list/') # 等待价格元素加载完成 page.wait_for_selector('span.btn-price', timeout=10000) # 获取渲染后的完整HTML html = page.content() browser.close() soup = BeautifulSoup(html, 'html.parser') array = [item.get_text() for item in soup.findAll('span', class_="btn-price")] newArr = [] for i in array: pattern = re.compile(r'\-?\d+\.\d+') diffPrices = list(map(float, re.findall(pattern, i))) newArr.append(str(diffPrices))
注意:服务器端需安装Playwright依赖,执行playwright install chromium完成浏览器环境配置。
3. 服务器IP被网站限制
服务器IP可能被目标网站反爬机制标记为异常,导致返回页面内容被过滤或重定向。
解决办法:
- 降低请求频率,添加随机延迟(如
import time; time.sleep(random.uniform(1,3))) - 使用代理IP发起请求,避免单一IP被封禁
- 检查服务器返回的HTML内容,确认是否包含Cloudflare验证、IP封禁提示等信息
4. 页面结构因访问环境差异变化
网站可能根据访问设备、地区返回不同HTML结构,服务器端拿到的页面与本地不一致,导致无法匹配btn-price类元素。
解决办法:
- 在服务器端打印
r.text的前500字符,对比本地请求的HTML内容,确认页面结构是否一致 - 若结构不同,调整BeautifulSoup的选择器,适配服务器端返回的页面结构
排查步骤建议
- 在服务器端打印
r.status_code,确认请求是否成功(200为正常状态) - 打印
r.text的部分内容,检查是否是目标页面,还是拦截提示页 - 对比本地和服务器端的请求头,确保关键标识(如User-Agent)一致
内容的提问来源于stack exchange,提问作者Jonathon Joel Moreno
相关产品推荐
相关产品推荐

