影刀RPA 酒店预订自动化:携程美团酒店数据采集与分析
什么情况用什么 → 怎么做 → 有什么坑
作者:林焱 | 飞行社出品
什么情况用什么
酒店行业需要监控竞品价格、分析入住率、跟踪评价变化。手动每天查几十家酒店的价格和评价,工作量巨大。
这套方案适合:
- 酒店管理者监控竞品价格
- OTA运营团队批量分析酒店数据
- 旅行社/企业差旅部门比价
核心工具:影刀RPA网页自动化 + 携程/美团/飞猪API(如果有) + 数据分析
怎么做
第一步:分析目标网站的数据获取方式
携程、美团酒店等平台没有公开API,需要用网页自动化或模拟API请求:
方案A:网页自动化(稳定但慢)
- 用影刀打开酒店列表页
- 滚动加载所有酒店
- 提取酒店名称、价格、评分、地址
拼多多店群自动化报活动上架!
- 点击进入详情页,提取更多信息
方案B:模拟API请求(快但不稳定)
- 用F12抓包,找到获取酒店列表的API接口
- 直接调用API获取JSON数据
- 绕过网页解析,效率提升10倍
importrequestsimportjsondeftry_find_hotel_api(city,checkin_date,checkout_date):"""尝试找到携程的酒店搜索API"""# 先请求网页,获取cookies和必要的参数session=requests.Session()list_url=f"https://hotels.ctrip.com/hotel/{city}.html"resp=session.get(list_url)# 分析页面,找API请求(实际抓包分析)# 携程的API通常是:# https://m.ctrip.com/restapi/soa2/16709.json (举例,实际会变)# 这里演示用网页自动化方案(更稳定)print("建议使用影刀网页自动化,API经常变化")returnNone# 实际落地推荐用影刀可视化流程第二步:用影刀采集酒店列表数据
在影刀中创建「酒店价格监控」流程:
【打开网页】https://hotels.ctrip.com/hotel/shanghai.html ↓ 【填写】目的地输入框 → "上海" ↓ 【填写】入住日期 → 明天 ↓ 【填写】离店日期 → 后天 ↓ 【点击】搜索按钮 ↓ 【等待元素出现】CSS: .hotel-list-item ↓ 【循环】遍历每个酒店卡片 ↓ 【提取数据】 - 酒店名称 (.hotel-name) - 价格 (.price-num) - 评分 (.score) - 地址 (.address) - 设施标签 (.facility-tag) ↓ 【写入Excel】保存到临时表 ↓ 【翻页】点击"下一页",继续采集(最多50页)Python辅助:处理动态加载
携程的酒店列表是滚动加载的(滚到页面底部才加载更多),需要用Python模拟滚动:
importpyautoguiimporttimedefscroll_to_load_all(driver):"""滚动页面,触发动态加载"""last_height=pyautogui.size()[1]# 页面初始高度whileTrue:# 滚动到页面底部pyautogui.press("end")time.sleep(2)# 等待加载# 检查是否还有"加载更多"按钮try:load_more=pyautogui.locateCenterOnScreen("load_more_btn.png",confidence=0.8)ifload_more:pyautogui.click(load_more)time.sleep(2)else:breakexcept:breakprint("页面已全部加载")第三步:采集酒店详情页数据
列表页信息有限,需要进入详情页采集更多数据(房型、用户评价、设施详情):
deffetch_hotel_detail(hotel_url):"""采集酒店详情页"""importrequestsfrombs4importBeautifulSoup headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...","Cookie":"你的Cookie"}resp=requests.get(hotel_url,headers=headers,timeout=10)soup=BeautifulSoup(resp.text,'html.parser')detail={}# 提取房型信息room_types=[]room_elements=soup.select(".room-type-item")forroominroom_elements:room_types.append({"房型":room.select_one(".room-name").text.strip(),"价格":room.select_one(".room-price").text.strip(),"设施":[facility.text.strip()forfacilityinroom.select(".room-facility")]})detail["房型"]=room_types# 提取用户评价摘要reviews=soup.select(".review-item")detail["好评率"]=soup.select_one(".good-rate").text.strip()ifsoup.select_one(".good-rate")else"N/A"detail["评价数"]=len(reviews)# 提取设施标签facilities=soup.select(".facility-tags span")detail["设施"]=[f.text.strip()forfinfacilities]returndetail# 批量采集(多线程加速)fromconcurrent.futuresimportThreadPoolExecutordefbatch_fetch_details(hotel_urls,max_workers=5):"""批量采集详情页"""withThreadPoolExecutor(max_workers=max_workers)asexecutor:futures=[executor.submit(fetch_hotel_detail,url)forurlinhotel_urls]results=[f.result()forfinfutures]returnresults第四步:价格监控与告警
importpandasaspdfromdatetimeimportdatetimedefmonitor_price_changes(hotel_id,new_price,threshold=0.1):""" 监控价格变化,超过阈值发送告警 threshold: 价格变化阈值(10%) """# 1. 从数据库读取上次价格conn=sqlite3.connect("hotel_price.db")cursor=conn.cursor()cursor.execute(""" SELECT price FROM price_history WHERE hotel_id = ? ORDER BY record_time DESC LIMIT 1 """,(hotel_id,))row=cursor.fetchone()conn.close()ifrow:old_price=row[0]change_pct=(new_price-old_price)/old_price# 价格变化超过阈值ifabs(change_pct)>threshold:send_price_alert(hotel_id,old_price,new_price,change_pct)returnTrue# 2. 记录新价格save_price_history(hotel_id,new_price)returnFalsedefsend_price_alert(hotel_id,old_price,new_price,change_pct):"""发送价格变化告警"""importrequests direction="上涨"ifchange_pct>0else"下降"webhook_url="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY"content=f""" 📈 **酒店价格预警** **酒店ID:**{hotel_id}**价格变化:**{old_price}元 →{new_price}元 **变化幅度:**{direction}{abs(change_pct)*100:.1f}% **时间:**{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}请及时调整定价策略! """payload={"msgtype":"markdown","markdown":{"content":content}}requests.post(webhook_url,json=payload)第五步:竞品分析与定价建议
defanalyze_competitor_pricing(hotel_id,radius_km=3):"""分析周边竞品价格,给出定价建议"""# 1. 获取目标酒店信息target=get_hotel_info(hotel_id)# 2. 获取周边竞品(同星级、同区域)competitors=get_nearby_hotels(target["latitude"],target["longitude"],radius_km)competitors=[hforhincompetitorsifh["star"]==target["star"]]# 3. 计算价格统计prices=[h["price"]forhincompetitors]avg_price=sum(prices)/len(prices)min_price=min(prices)max_price=max(prices)# 4. 给出定价建议current_price=target["price"]ifcurrent_price>avg_price*1.2:suggestion=f"⚠️ 你的价格高于周边均价20%,建议降至{int(avg_price*1.1)}元左右"elifcurrent_price<avg_price*0.8:suggestion=f"💰 你的价格低于周边均价20%,可以涨到{int(avg_price*0.95)}元左右"else:suggestion=f"✅ 你的价格与周边均价持平,保持{int(avg_price)}元左右即可"return{"周边酒店数":len(competitors),"周边均价":int(avg_price),"最低价":min_price,"最高价":max_price,"定价建议":suggestion}第六步:影刀RPA完整流程编排
【定时触发】每天早上6点(早于用户预订时间) ↓ 【读取配置文件】加载要监控的酒店列表(Excel) ↓ 【循环】遍历每个酒店 ↓ 【打开网页】携程/美团酒店详情页 ↓ 【提取价格】用XPath提取当前价格 ↓ 【Python节点】monitor_price_changes() → 检测价格变化 ↓ 【条件判断】价格变化超过10%? ├─ 是 → 【企微通知】发送价格预警 └─ 否 → 继续 ↓ 【写入数据库】记录今日价格 ↓ 【生成日报】(所有酒店处理完后) → 生成"酒店价格监控日报.xlsx" → 包含:酒店名、今日价、昨日价、7日均价、竞品对比 → 发送给酒店运营团队有什么坑
坑1:网站反爬虫——IP被封
携程/美团都有严格的反爬策略:
- 同一IP短时间大量请求 → 弹出验证码或直接封IP
- 不携带Cookie → 返回虚假价格(诱饵数据)
解决方案:
# 1. 使用代理IP池importrandom PROXY_POOL=["http://proxy1:8080","http://proxy2:8080",# ...]deffetch_with_proxy(url):proxy=random.choice(PROXY_POOL)resp=requests.get(url,proxies={"http":proxy,"https":proxy},timeout=10)returnresp# 2. 每次请求随机延迟importtimeimportrandom time.sleep(random.uniform(2,5))# 每次请求间隔2-5秒# 3. 使用真实浏览器Cookie# 在浏览器登录携程,F12→Network→复制Cookieheaders={"Cookie":"your_cookie_here","User-Agent":"Mozilla/5.0 ..."}坑2:动态内容加载不全
TEMU店群矩阵自动化运营核价报活动
酒店详情页的"用户评价"部分是滚动加载的,页面初始只显示5条,需要滚动才能加载更多。
解决方案:用影刀的【模拟操作】指令,循环执行"滚动到评价区域→等待加载→继续滚动",直到没有新内容出现。
坑3:价格因用户身份不同而不同(大数据杀熟)
同一家酒店,不同用户看到的价格可能不一样(新用户优惠、会员折扣、历史消费记录等)。
解决方案:使用无痕浏览器或者清理Cookie后再访问,获取"标准价格":
# 用Selenium启动无痕模式fromseleniumimportwebdriverfromselenium.webdriver.chrome.optionsimportOptions chrome_options=Options()chrome_options.add_argument("--incognito")# 无痕模式chrome_options.add_argument("--disable-blink-features=AutomationControlled")# 绕过反爬检测driver=webdriver.Chrome(options=chrome_options)driver.get("https://hotels.ctrip.com/hotel/12345.html")坑4:数据量太大,Excel存不下
如果监控1000家酒店,每天采集一次,一年就是36万条数据,Excel根本存不下。
解决方案:用数据库存储(SQLite/MySQL):
defsave_to_database(hotel_id,price,date):"""保存价格数据到数据库"""conn=sqlite3.connect("hotel_price.db")cursor=conn.cursor()# 创建表(如果不存在)cursor.execute(""" CREATE TABLE IF NOT EXISTS price_history ( id INTEGER PRIMARY KEY AUTOINCREMENT, hotel_id TEXT, price REAL, record_date TEXT, record_time TEXT ) """)# 插入数据cursor.execute(""" INSERT INTO price_history (hotel_id, price, record_date, record_time) VALUES (?, ?, ?, ?) """,(hotel_id,price,date,datetime.now().strftime("%Y-%m-%d %H:%M:%S")))conn.commit()conn.close()总结
| 平台 | 数据质量 | 反爬难度 | 推荐指数 |
|---|---|---|---|
| 携程 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| 美团酒店 | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| 飞猪 | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
| Booking | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐ |
实际落地建议:
- 先小范围测试:选10家竞品酒店,每天采集一次,跑一周看稳定性
- 用影刀可视化流程:比纯代码更稳定,维护成本低
- 做好异常处理:网页加载失败、数据提取失败要有重试机制
- 遵守robots.txt:不要给目标网站造成过大压力
如果需要更稳定的数据,可以考虑购买携程/美团的商家API(需要企业资质),这样就能合法合规地获取数据时了。