在餐饮外卖行业,商家评分和销量是消费者决策的核心依据。对于商家运营者,分析竞品数据可优化定价策略;对于市场调研者,掌握区域销量分布能洞察消费趋势。美团外卖作为国内最大外卖平台,其数据具有极高的商业价值。但手动收集效率低下,本文将通过Python爬虫技术,实现自动化数据采集。

美团采用AJAX动态加载技术,商家列表和详情页数据通过接口分批获取。例如:
https://meishi.meituan.com/api/v1/poi/listpip install requests beautifulsoup4 selenium pandas fake_useragent
安装ChromeDriver(需与浏览器版本匹配),配置环境变量。
import requests
from bs4 import BeautifulSoup
import pandas as pd
def get_static_data(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'html.parser')
shops = []
for item in soup.find_all('div', class_='shop-item'):
name = item.find('h3').text.strip()
rating = item.find('span', class_='rating').text
sales = item.find('span', class_='sales').text.split('月售')[1].strip()
shops.append({'name': name, 'rating': rating, 'sales': sales})
return pd.DataFrame(shops)
# 示例调用
df = get_static_data('https://www.meituan.com/meishi/')
df.to_csv('meituan_static.csv', index=False)
问题:此方法仅能获取首屏数据,后续内容需滚动加载。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
def get_dynamic_data(url):
options = webdriver.ChromeOptions()
options.add_argument('--headless') # 无头模式
driver = webdriver.Chrome(options=options)
driver.get(url)
# 模拟滚动加载
for _ in range(5):
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(2)
# 解析动态加载的元素
shops = []
items = driver.find_elements(By.CSS_SELECTOR, '.shop-item')
for item in items:
name = item.find_element(By.CSS_SELECTOR, 'h3').text
rating = item.find_element(By.CSS_SELECTOR, '.rating').text
sales = item.find_element(By.CSS_SELECTOR, '.sales').text.split('月售')[1]
shops.append({'name': name, 'rating': rating, 'sales': sales})
driver.quit()
return pd.DataFrame(shops)
# 示例调用
df = get_dynamic_data('https://www.meituan.com/meishi/')
df.to_csv('meituan_dynamic.csv', index=False)
优化点:
time.sleep()模拟人类操作节奏通过Chrome开发者工具(F12)的Network面板,捕获商家列表请求:
import requests
import json
def get_api_data(city_id, offset=0):
url = f"https://meishi.meituan.com/api/v1/poi/list?cityId={city_id}&offset={offset}&limit=20"
headers = {
'Referer': 'https://www.meituan.com/meishi/',
'User-Agent': 'Mozilla/5.0...'
}
response = requests.get(url, headers=headers)
data = json.loads(response.text)
shops = []
for poi in data.get('data', []):
shops.append({
'name': poi['title'],
'rating': poi['avgScore'],
'sales': poi['recentSalesNum'],
'address': poi['address']
})
return shops
# 示例:获取北京前40家商家数据
all_shops = []
for i in range(2): # 每页20条,获取2页
all_shops.extend(get_api_data(city_id=1, offset=i*20))
pd.DataFrame(all_shops).to_csv('meituan_api.csv', index=False)
优势:
import random
from fake_useragent import UserAgent
proxies = [
{'http': 'http://123.123.123.123:8080'},
{'http': 'http://124.124.124.124:8081'}
]
def get_with_proxy(url):
proxy = random.choice(proxies)
headers = {'User-Agent': UserAgent().random}
try:
return requests.get(url, headers=headers, proxies=proxy, timeout=5)
except:
return get_with_proxy(url) # 失败自动重试
headers = {
'Accept': 'application/json',
'Referer': 'https://www.meituan.com/',
'X-Requested-With': 'XMLHttpRequest',
'Cookie': 'your_cookie_here' # 必要时携带合法Cookie
}
import time
import random
def request_with_delay(url):
delay = random.uniform(1, 3) # 1-3秒随机延迟
time.sleep(delay)
return get_with_proxy(url)
# 存储为CSV
df.to_csv('meituan_data.csv', index=False, encoding='utf_8_sig')
# 存储到MySQL
import pymysql
from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://user:password@localhost/meituan')
df.to_sql('shops', engine, if_exists='replace', index=False)
import matplotlib.pyplot as plt
# 评分分布饼图
ratings = df['rating'].value_counts()
plt.pie(ratings, labels=ratings.index, autopct='%1.1f%%')
plt.title('商家评分分布')
plt.show()
# 销量TOP10柱状图
top10 = df.nlargest(10, 'sales')
plt.barh(top10['name'], top10['sales'])
plt.xlabel('月销量')
plt.title('销量TOP10商家')
plt.show()
Q1:被网站封IP怎么办?
A:立即启用备用代理池,建议使用住宅代理(如站大爷IP代理),配合每请求更换IP策略。若使用Selenium,可结合selenium-wire库自动轮换代理。
Q2:如何获取特定区域的商家数据?
A:通过API接口的cityId参数指定城市,或解析页面URL中的区域标识(如/meishi/bj/代表北京)。
Q3:数据缺失或格式错误如何处理? A:在解析阶段添加异常处理:
try:
rating = float(item['avgScore'])
except (KeyError, ValueError):
rating = 0.0
Q4:如何避免被法律风险? A:严格遵守《网络安全法》,仅爬取公开数据,避免高频请求(建议延迟≥3秒),不存储敏感信息。商业用途前建议咨询法律顾问。
Q5:Selenium爬取时出现元素未加载怎么办? A:使用显式等待替代固定延迟:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, '.shop-item'))
)
本文通过三种技术方案(静态解析、Selenium模拟、API直连)实现了美团外卖数据采集,核心要点包括:
进阶方向:
数据采集的本质是信息获取效率的竞赛,但始终需牢记:技术应服务于正当需求,合规性比技术实现更重要。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。