前言
在数据分析和商业智能领域,餐厅和商户信息的采集是一个常见需求。Yelp作为全球知名的本地商户评论平台,包含了大量有价值的商户信息。本文将详细介绍如何使用Python开发一个高效的Yelp数据爬虫,实现商户信息的批量采集。
技术栈介绍
本项目采用以下技术栈:
- Python 3.x:主要编程语言
- curl_cffi:用于发送HTTP请求,支持浏览器指纹模拟
- 正则表达式:用于数据解析
- JSON处理:解析API响应数据
项目架构设计
核心类:YelpSearchUser
我们设计了一个YelpSearchUser类来封装所有的爬虫功能,主要包含以下几个核心方法:
__init__()- 初始化请求头和配置项get()- 获取搜索结果列表get_detail()- 获取商户详细信息parse_data()- 解析搜索结果parse_data_detail()- 解析详细信息
详细实现分析
1. 初始化配置
def __init__(self):
self.headers = {
"accept": "*/*",
"accept-language": "zh-CN,zh;q=0.9",
"cache-control": "no-cache",
"pragma": "no-cache",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
在初始化方法中,我们设置了两套请求头:
headers:用于API请求html_headers:用于页面请求
这样做的目的是为了更好地模拟真实浏览器行为,避免被反爬虫机制检测。
2. Cookie处理机制
def cookie_str_to_dict(self, cookie_str: str) -> dict:
cookie_dict = {}
cookies = [i.strip() for i in cookie_str.split('; ') if i.strip() != ""]
for cookie in cookies:
key, value = cookie.split('=', 1)
cookie_dict[key] = value
return cookie_dict
Cookie是维持会话状态的关键,我们实现了Cookie字符串到字典的转换功能,确保请求的连续性。
3. 搜索功能实现
def get(self, page, find_desc, find_loc=""):
url = "https://www.yelp.com/search/snippet"
if page == 1:
params = {
"find_desc": find_desc,
"find_loc": find_loc,
"parent_request_id": "097f2346bb4acfc4",
"request_origin": "user"
}
else:
start = f"{(page-1)*10}"
params = {
"find_desc": find_desc,
"find_loc": find_loc,
"start": start,
"parent_request_id": "097f2346bb4acfc4",
"request_origin": "user"
}
搜索功能支持分页,通过start参数控制结果偏移量,每页显示10条结果。
4. 数据解析核心算法
搜索结果解析
def parse_data(self, data_list):
resultList = []
for d in data_list:
try:
bizId = d.get('bizId')
if not bizId:
continue
p_url = "https://www.yelp.com"+d['searchResultBusiness'].get('businessUrl','')
item = [bizId, p_url]
resultList.append(item)
except Exception as e:
print("解析错误:", e)
return resultList
详细信息解析
def parse_data_datail(self, html, bizId, p_url):
html = html.replace(""", '"').replace("/", "/")
data_text = "".join(re.findall('<!--\{(.*?)--></script><!-- PRAGMA_YELP_BEGIN_RESPONSE', html))
data_text = "{" + data_text
dataJson = json.loads(data_text)
bs = dataJson[f"Business:{bizId}"]
# 提取各种商户信息
name = bs.get('name', '')
reviewCount = bs.get('reviewCount', 0)
rating = bs.get('rating({"roundingMethod":"NEAREST_TENTH"})', '0.0')
# ... 更多字段解析
这里使用了正则表达式提取页面中的JSON数据,然后解析出我们需要的商户信息。
数据字段说明
我们提取的商户信息包括:
| 字段名 | 描述 | 示例 |
|---|---|---|
| bizId | 商户唯一标识 | "abc123def456" |
| name | 商户名称 | "老北京烤鸭店" |
| rating | 评分 | "4.5" |
| reviewCount | 评论数量 | 128 |
| phoneNumber | 电话号码 | "+1-555-123-4567" |
| address | 地址 | "123 Main St, New York" |
| website_url | 官网链接 | "https://example.com" |
| operationHours | 营业时间 | "9:00 AM - 10:00 PM" |
使用示例
if __name__ == '__main__':
ysu = YelpSearchUser()
# 设置Cookie(从浏览器复制)
cookies = 'your_cookie_string_here'
# 搜索参数
keyword = '' # 搜索关键词,空字符串表示搜索所有
location = 'Tokyo' # 搜索地点
page = 1 # 页码
# 获取搜索结果
data = ysu.main(keyword, location, page, cookies, proxies=None)
# 获取每个商户的详细信息
for url in data['item_list']:
result = ysu.main_detail(url, cookies, proxies=None)
print(result)
技术亮点
1. 浏览器指纹模拟
使用curl_cffi库的impersonate="chrome131"参数,完美模拟Chrome浏览器的TLS指纹和HTTP/2特征。
2. 错误处理机制
while True:
try:
response = requests.get(url, headers=self.headers, ...)
if status_code == 200:
return response.json(), status_code
else:
return None, status_code
except Exception as e:
print("发生错误:", e)
采用无限循环重试机制,确保网络波动不会影响数据采集。
3. 代理支持
代码支持代理服务器配置,可以通过proxies参数设置代理,提高采集成功率。
注意事项
1. 法律合规
- 遵守Yelp的服务条款
- 控制请求频率,避免对服务器造成压力
- 仅用于学习和研究目的
2. 技术注意点
- Cookie需要定期更新
- 建议添加随机延时避免被检测
- 可以配置用户代理轮换
3. 异常处理
- 网络超时处理
- JSON解析异常处理
- 数据缺失情况处理
总结
本文介绍了一个完整的Yelp数据爬虫实现,涵盖了从搜索到详细信息获取的全流程。通过合理的架构设计和技术选型,实现了高效稳定的数据采集。
这个爬虫项目不仅适用于Yelp,其设计思路和技术方案也可以应用到其他类似的数据采集场景中。希望本文能为大家在爬虫开发方面提供有价值的参考。
相关资源
- curl_cffi官方文档
- Python正则表达式教程
- HTTP请求头详解
本文仅供学习交流使用,请遵守相关法律法规和网站服务条款。



















