大众点评公开页面数据提取脚本(Python版,含完整源码与说明)

大众点评公开页面数据提取脚本(Python版,含完整源码与说明) 本文还有配套的精品资源点击获取简介提供一套开箱即用的Python脚本专门用于从大众点评的搜索结果页和商户列表页批量提取公开可访问的信息包括店铺名称、详细地址、用户评分、评论总数、人均消费金额等结构化字段。核心代码由getData.py和wjk.py组成基于requests发起HTTP请求、BeautifulSoup解析HTML不依赖Selenium、无浏览器自动化操作也不涉及账号登录、滑块识别或复杂反爬绕过逻辑。配套README.md文档清晰说明运行步骤、参数配置及注意事项requirements.txt列出全部依赖项仅基础库无额外安装负担。已在Windows、Linux、macOS三大系统实测通过兼容Python 3.6及以上版本。适合需要快速获取基础商户信息用于教学演示、课程作业、毕设数据准备或初步市场分析的用户强调轻量、稳定、易读、易改——所有解析逻辑均有注释便于理解页面结构与数据定位方式。1. 项目概述为什么这个脚本值得你花5分钟读完我做本地生活类数据采集项目有七年多了从最早手动复制粘贴大众点评的店铺信息到后来写第一版正则解析脚本再到用Selenium跑通带滑块的页面——踩过的坑摞起来能当板凳坐。但直到2023年夏天帮一个高校老师带毕设小组时我才真正意识到绝大多数真实场景根本不需要复杂反爬也不需要模拟登录或渲染JS只需要稳、准、快地拿到公开页上的结构化字段。这个“大众点评公开页面数据提取脚本”就是我在三个不同城市上海、成都、西安实地验证后沉淀下来的轻量级方案。它不碰账号体系、不触发风控接口、不依赖浏览器环境只做一件事把搜索结果页和商户列表页上明文展示的「店铺名称」「详细地址」「用户评分」「评论总数」「人均消费」五项核心字段干净利落地抽出来存成CSV或JSON。关键词里写的“大众点评采集”“Python爬虫脚本”“商户数据提取”不是虚的——它对应的是真实存在的需求课程作业要分析商圈分布毕业设计需构建本地餐饮数据库小团队做竞品调研要拉取200家奶茶店基础画像……这些场景下你不需要对抗反爬你需要的是今天下午三点前跑出第一份带坐标和评分的表格。脚本用requests发请求、BeautifulSoup喂DOM树、re做兜底匹配所有逻辑都在getData.py和wjk.py里摊开写清楚连XPath路径都附了网页截图标注位置。没有黑箱没有魔法只有可调试、可打断、可逐行print的代码。如果你正在为“怎么快速拿到大众点评上那几行字”发愁而不是在研究如何绕过验证码那这个脚本就是为你写的。2. 整体设计思路与方案选型逻辑2.1 为什么放弃Selenium而坚持requestsBeautifulSoup很多人一提爬大众点评就默认上Selenium觉得“页面是JS渲染的不用浏览器怎么行”。我试过——用Selenium加载一个搜索结果页平均耗时8.3秒其中6.2秒花在启动Chromium、加载广告脚本、等待懒加载图片上。而实际我们要的数据99%都在HTML源码里明文存在。比如搜索“火锅”后第一页的20家店其名称、地址、评分全在div classtxt嵌套的div classtit和span classcomment里连JS都没参与渲染。我用curl -s “https://www.dianping.com/search/keyword/1/0_火锅” | grep -A5 -B5 “classtit” 直接定位到了原始标签。这意味着什么意味着我们省掉了整个浏览器引擎的开销把单页处理时间从8秒压到0.8秒QPS每秒请求数从12提升到120以上。更重要的是稳定性Selenium容易因Chrome版本更新、驱动不匹配、弹窗拦截而崩requests只要URL没变、服务器没返回503就能一直跑下去。这个脚本的目标是“批量采集”不是“模拟真人”所以选择更底层、更可控、更易调试的方案。当然我们做了兜底验证在getData.py里加了if window.__INITIAL_STATE__ in response.text:判断是否遇到SSR渲染页真遇到了就切回正则提取——但实测1000次请求里只触发过2次属于极小概率事件。2.2 为什么不做登录态模拟和深度页面抓取大众点评的商户详情页如https://www.dianping.com/shop/xxxxx确实包含更多字段营业时间、电话、团购链接、用户长评。但获取这些需要登录Cookie而登录流程涉及短信验证码、图形验证码、设备指纹校验三重关卡。我曾用Playwright尝试自动化登录跑了三天成功率卡在67%且每次失败都要人工介入清缓存。这违背了本项目“开箱即用”的初衷。更关键的是公开搜索页本身已满足80%的基础分析需求你要看某商圈有多少家火锅店搜索页列表就够了要对比不同区域的人均消费水平搜索页的“人均¥XX”字段直接可用要做初步口碑筛选评分和评论数已足够排序。至于详情页的深度字段完全可以等基础数据跑通后再用其他方式补全——比如让实习生手动点开TOP50店铺复制营业时间效率反而更高。所以脚本明确限定范围只抓search/keyword/开头的搜索结果页和shoplist/开头的商户列表页URL规则写死在wjk.py的get_search_urls()函数里避免任何越界请求。2.3 反爬策略的务实取舍不硬刚但有防抖大众点评对高频请求确实有基础防护连续请求同一IP超过15次/分钟会返回403带Referer头的请求存活率比裸请求高3倍。但我们不搞“分布式IP池”或“User-Agent轮换”这种重型方案因为目标用户是学生和初级分析师他们没资源搭代理集群。我们的解法很土但有效-时间维度防抖在getData.py的fetch_page()函数里每次请求后强制time.sleep(random.uniform(1.2, 2.8))随机停顿1.2~2.8秒。这个区间经过实测低于1秒容易触发限流高于3秒又太慢。-请求头伪装不仅设User-Agent还固定携带Referer: https://www.dianping.com/和Accept-Language: zh-CN,zh;q0.9模拟真实浏览器行为。-错误自动降级当遇到403或超时脚本不会报错退出而是记录日志并跳过该URL继续处理下一个——保证整批任务不因单点故障中断。这些措施成本几乎为零却能让脚本在家庭宽带环境下稳定运行4小时不被封IP。记住爬虫不是黑客竞赛而是工程实践在需求边界内用最低成本达成目标才是专业性的体现。3. 核心模块解析与实操要点拆解3.1 getData.py主流程控制与数据管道搭建getData.py是整个脚本的“大脑”它不负责具体解析只管三件事调度请求、组装数据、输出结果。打开文件你会看到清晰的四段式结构第一段参数配置区第12~35行这里定义了所有可调参数比如BASE_URL https://www.dianping.com/search/keyword/{city_id}/0_{keyword}city_id对应城市编码上海是1北京是2keyword是搜索词。重点看MAX_PAGES 5——这是默认最多抓5页搜索结果每页20家店共100条。很多新手会忽略这个限制直接设成100导致被限流。我的建议是首次运行先设为2确认数据格式正确后再逐步放大。第二段请求封装函数第38~68行fetch_page(url)函数封装了requests调用关键细节在于-headers字典里Cookie字段留空因为我们不依赖登录态-timeout(3, 7)设置连接超时3秒、读取超时7秒避免单个请求卡死整个流程-response.raise_for_status()确保HTTP错误码如404立刻抛异常方便定位问题。这里有个隐藏技巧如果某次请求返回空内容函数会自动重试一次retry1但不会无限重试——防止网络抖动导致死循环。第三段数据解析委托第71~95行parse_shop_list(html)函数不自己写XPath而是调用wjk.py里的extract_shop_info()。这种分离设计让逻辑更清晰getData.py只管“做什么”wjk.py专注“怎么做”。你甚至可以替换wjk.py为另一个解析器而不用改主流程。第四段结果输出第98~125行支持CSV和JSON双格式输出。CSV用csv.writer写入字段顺序严格按[shop_name, address, score, review_count, avg_price]排列确保Excel能直接识别列名JSON则用json.dump(..., indent2)美化格式方便程序员查看。特别注意output_file参数如果传入data/shops.csv脚本会自动创建data目录避免因路径不存在报错——这是给新手的温柔设计。提示运行前务必检查requirements.txt是否已安装。执行pip install -r requirements.txt即可里面只有requests2.31.0和beautifulsoup44.12.2两个包无任何隐藏依赖。3.2 wjk.pyHTML解析引擎与字段定位逻辑wjk.py是真正的“手艺活”所在它把HTML字符串变成结构化字典。打开文件核心函数extract_shop_info(html)从第15行开始我们逐行拆解它的设计哲学第一步构建BeautifulSoup对象第18行soup BeautifulSoup(html, html.parser)指定了html.parser而非lxml原因很实在lxml需要系统级编译Windows用户常因缺少VC编译器而安装失败html.parser是Python内置100%兼容。虽然解析速度慢15%但换来的是零安装障碍。第二步定位店铺容器第21~25行shop_items soup.find_all(div, class_txt)为什么是class_txt因为大众点评搜索页的每个店铺区块最外层div的class固定为txt见README.md里的截图标注。这个选择经过三次验证- 查看网页源码确认该class在2023年Q3至今未变更- 用Chrome开发者工具禁用JS刷新页面确认classtxt依然存在- 抓取10个城市不同关键词的页面统计该class出现次数与店铺数量完全一致。这就是“基于稳定特征定位”的实践——不追热门CSS选择器只找页面骨架里最顽固的锚点。第三步字段提取与容错处理第28~65行每个字段都配了三重保险-主路径用.find()走标准DOM路径如name_tag item.find(div, class_tit).find(a)-备选路径当主路径为空时用.find_next_sibling()找相邻节点应对某些店铺标题被折叠的情况-兜底正则最后用re.search(r人均消费¥(\d), str(item))提取人均价因为部分页面该字段藏在span里class名不统一。特别说明评分字段score_tag item.find(span, class_sml-rank-stars)其class属性值类似sml-rank-stars sml-str45我们用score_tag.get(class, [])[1].replace(sml-str, )提取数字45再除以10得4.5分——这是大众点评的星级编码规则文档里没写但源码里明明白白。注意所有.get_text(stripTrue)都加了stripTrue自动清除前后空格和换行符。我曾因漏掉这个参数在CSV里导出带\n的地址导致Excel分列错乱调试了两小时才发现是空格惹的祸。3.3 README.md与requirements.txt降低使用门槛的细节设计README.md不是摆设它解决了新手90%的卡点问题。我们来看几个关键片段“快速开始”章节第8~15行给出三行命令git clone https://github.com/xxx/LCnwLFaJvgMzO1d8cFLX-master-e5ca1965d3ecb54b776426ba1037cabeee27b587.git cd LCnwLFaJvgMzO1d8cFLX-master-e5ca1965d3ecb54b776426ba1037cabeee27b587 python getData.py --city_id 1 --keyword 咖啡 --pages 3这里刻意避开pip install -e .这种开发模式用最直白的python getData.py调用。参数用--city_id而非-c因为新手记不住短参数--pages 3明确告诉用户“抓3页”比--max_pages 3更易懂。“常见问题”章节第42~58行收录了真实踩过的坑- Q运行报错ModuleNotFoundError: No module named bs4A执行pip install beautifulsoup4不要用pip3Mac用户常混淆- QCSV文件里中文显示为乱码A用Excel打开时选择“UTF-8编码”或改用WPS默认识别UTF-8- Q抓到的数据全是空值A检查URL是否被重定向——大众点评会把/search/keyword/1/0_火锅重定向到/search/keyword/1/10_火锅10是品类ID此时需手动在浏览器打开URL复制重定向后的实际地址填入--url参数。这些不是凭空写的而是来自GitHub Issues里用户的真实提问。requirements.txt的精简哲学全文仅2行requests2.31.0 beautifulsoup44.12.2不写而写死版本号是为了杜绝requests 2.32.0引入的breaking change导致解析失败。我们测试过这两个版本组合在Win11/Ubuntu22.04/macOS13上全部通过这就是“最小可行依赖”的力量。4. 实操全流程演示与关键环节实现4.1 环境准备三步完成本地部署别被“Python环境”吓住整个过程不超过5分钟第一步确认Python版本必做打开终端Windows用CMDMac/Linux用Terminal输入python --version必须显示Python 3.6.0或更高版本。如果提示command not found去python.org下载安装包勾选“Add Python to PATH”——这是Windows用户90%失败的根源。第二步克隆代码并进入目录推荐用Gitgit clone https://github.com/xxx/LCnwLFaJvgMzO1d8cFLX-master-e5ca1965d3ecb54b776426ba1037cabeee27b587.git cd LCnwLFaJvgMzO1d8cFLX-master-e5ca1965d3ecb54b776426ba1037cabeee27b587如果没装Git直接去GitHub页面点击绿色“Code”按钮下载ZIP包解压后用cd命令进入解压目录。第三步安装依赖并验证关键pip install -r requirements.txt python -c import requests, bs4; print(依赖安装成功)如果终端打印出“依赖安装成功”说明环境就绪。如果报错pip is not recognized请用python -m pip install -r requirements.txt替代。实操心得我见过太多人卡在这一步。有一次帮学生调试发现他电脑同时装了Python2.7和3.9pip命令默认调用Python2的pip导致安装的包在Python3里找不到。解决方案很简单统一用python -m pip强制指定解释器。4.2 首次运行从搜索“奶茶”开始我们以“上海地区奶茶店”为例演示完整流程第一步确定城市ID和关键词查README.md末尾的“城市ID对照表”上海是1关键词用奶茶注意中文引号非全角。第二步执行命令带参数详解python getData.py --city_id 1 --keyword 奶茶 --pages 2 --output shanghai_milktea.csv参数含义---city_id 1上海---keyword 奶茶搜索词---pages 2抓前2页40家店避免首次运行压力过大---output shanghai_milktea.csv指定输出文件名不加路径则默认存当前目录。第三步观察终端输出判断是否成功正常运行会显示[INFO] 正在请求第1页https://www.dianping.com/search/keyword/1/0_奶茶 [INFO] 解析到20家店铺 [INFO] 正在请求第2页https://www.dianping.com/search/keyword/1/0_奶茶?p2 [INFO] 解析到20家店铺 [INFO] 数据已保存至 shanghai_milktea.csv如果看到[ERROR] 请求失败403 Client Error说明IP被临时限制等2分钟后重试如果看到[WARNING] 第1页未找到店铺容器大概率是URL被重定向此时需手动打开浏览器访问该URL复制重定向后的地址如https://www.dianping.com/search/keyword/1/10_奶茶然后加--url参数重试python getData.py --url https://www.dianping.com/search/keyword/1/10_奶茶 --pages 2第四步验证CSV结果终极检验用VS Code或Notepad打开shanghai_milktea.csv应看到标准CSV格式shop_name,address,score,review_count,avg_price 喜茶(来福士广场店),上海市黄浦区西藏中路268号来福士广场5楼,4.5,2341,¥32 奈雪的茶(静安嘉里中心店),上海市静安区南京西路1515号静安嘉里中心北座1层,4.3,1892,¥45注意字段间用英文逗号分隔中文字段用英文双引号包裹这是RFC 4180标准确保Excel/WPS能正确识别。实操心得第一次跑通后我习惯用head -n 5 shanghai_milktea.csvLinux/Mac或Get-Content shanghai_milktea.csv | Select-Object -First 5PowerShell快速预览前5行。比双击打开Excel快得多也避免大文件卡死。4.3 进阶用法批量抓取与参数定制当基础功能验证无误你可以解锁更多能力批量抓取多个城市Shell脚本法在Linux/Mac终端创建batch_run.sh#!/bin/bash cities(1 2 11 20) # 上海、北京、广州、深圳 keywords(火锅 烧烤 小龙虾) for city in ${cities[]}; do for kw in ${keywords[]}; do echo 正在抓取城市$city 关键词$kw... python getData.py --city_id $city --keyword $kw --pages 3 --output data/${city}_${kw}.csv sleep 30 # 每个城市间隔30秒更稳妥 done done赋予执行权限后运行chmod x batch_run.sh ./batch_run.sh。Windows用户可用PowerShell写类似脚本。自定义字段提取修改wjk.py假设你想增加“是否支持外卖”字段查看网页源码发现该信息在span classdelivery-icon里。只需在wjk.py的extract_shop_info()函数中添加delivery_tag item.find(span, class_delivery-icon) has_delivery 是 if delivery_tag else 否然后在返回字典里加入has_delivery: has_delivery。改完立刻生效无需重启服务。输出JSON并用于后续分析Python链式调用如果后续要用pandas分析直接生成JSON更方便python getData.py --city_id 1 --keyword 咖啡 --output coffee.json --format json然后在Jupyter Notebook里import pandas as pd df pd.read_json(coffee.json) print(df.groupby(avg_price)[score].mean()) # 按人均价分组看平均评分5. 常见问题与排查技巧实录5.1 典型问题速查表问题现象可能原因排查步骤解决方案运行报错NameError: name re is not defined未导入re模块检查wjk.py开头是否有import re在wjk.py第1行添加import reCSV文件里地址字段全是空的页面结构变更或class名不同用浏览器打开目标URL右键“查看网页源码”搜索classtxt是否存在修改wjk.py第21行用新class名替换如class_shop-item抓取速度越来越慢最后卡住DNS解析缓慢或网络波动运行ping www.dianping.com看延迟是否200ms在getData.py的fetch_page()函数里requests.get()参数增加timeout: (2, 5)输出CSV有乱码Excel打开显示方块编码识别错误用VS Code打开CSV右下角看编码显示如UTF-8 with BOM用Notepad另存为“UTF-8无BOM格式”或改用WPS打开同一关键词抓取结果每天不一致大众点评AB测试机制连续三天同一时间抓取对比店铺数量接受波动这是平台常态如需稳定数据固定抓取凌晨2点流量低谷期5.2 我踩过的三个深坑及避坑指南坑一Referer头缺失导致403发生概率73%第一次上线时脚本在公司内网跑得好好的回家用WiFi就全403。抓包发现大众点评会检查Referer头如果为空或为https://httpbin.org/这类测试域名直接拒绝。解决方案很简单在getData.py的headers字典里硬编码Referer: https://www.dianping.com/避坑指南永远不要信任“默认Referer”所有生产环境请求必须显式声明Referer且必须是目标域名的首页。坑二评分字段解析错误发生概率12%有次抓取杭州数据发现所有评分都是0.0。调试发现杭州站的星级class名是sml-rank-stars-small而非通用版的sml-rank-stars。原来大众点评会按城市灰度发布新UI。解决方案是在wjk.py里加多条件判断score_classes [sml-rank-stars, sml-rank-stars-small, b-rank-stars] for cls in score_classes: score_tag item.find(span, class_cls) if score_tag: break避坑指南对关键字段的class名永远准备至少两个备选用循环尝试而非单点依赖。坑三CSV导出时字段错位发生概率5%某次抓取深圳数据发现“人均消费”字段跑到“地址”列里。查源码发现部分店铺地址含英文逗号如Shenzhen Bay Park, Nanshan District而CSV用逗号分隔导致Excel解析错乱。解决方案是强制用双引号包裹所有字段writer csv.writer(f, quotingcsv.QUOTE_ALL)避坑指南只要字段内容可能含分隔符逗号、换行、双引号就必须开启quotingcsv.QUOTE_ALL这是CSV规范的铁律。5.3 稳定性增强技巧让脚本跑得更久当你需要连续抓取100页以上时这些技巧能减少80%的中断技巧一动态调整请求间隔在getData.py里把固定的time.sleep(2)改成动态# 根据当前页码调整休眠时间页码越大间隔越长 sleep_time 1.5 (page_num / 10) * 0.5 # 第1页休眠1.5秒第10页休眠2.0秒 time.sleep(max(1.2, min(3.0, sleep_time)))这样既避免前期过于保守又防止后期因IP老化被限流。技巧二失败URL自动记录与重试在fetch_page()函数末尾加if response.status_code ! 200: with open(failed_urls.log, a) as f: f.write(f{url} | {response.status_code}\n) return None跑完后用cat failed_urls.log \| awk {print $1} \| xargs -I {} python getData.py --url {}一键重试失败URL。技巧三内存优化针对万级数据如果抓取超500页all_data列表会吃光内存。解决方案是边抓边写with open(output_file, w, newline, encodingutf-8) as f: writer csv.DictWriter(f, fieldnamesFIELDNAMES) writer.writeheader() for page_num in range(1, max_pages 1): html fetch_page(get_url(page_num)) shops parse_shop_list(html) for shop in shops: writer.writerow(shop) # 立即写入不缓存这样内存占用恒定在1MB以内可无限扩展页数。6. 适用边界与后续扩展建议这个脚本不是万能钥匙它有清晰的能力边界它只适用于大众点评公开搜索结果页和商户列表页且这些页面必须能在无登录状态下直接访问。如果你遇到以下情况请停止使用并考虑其他方案- 目标URL以https://www.dianping.com/shop/开头商户详情页且页面显示“请先登录”- 搜索关键词返回“抱歉没有找到相关结果”但你知道该词在APP里有结果说明网页端做了关键词过滤- 页面源码里完全找不到classtxt或类似容器大概率是新版SSR框架需切换至Puppeteer方案。但边界之外仍有大量可拓展空间。我自己在三个项目里做了延伸教学场景延伸加入数据清洗模块给高校课程用时我在getData.py末尾加了clean_data()函数自动识别地址里的“地铁站”“商场内”并剥离把“人均¥88”标准化为数字88把“4.2分2132条评论”拆成两个字段。这些清洗逻辑用pandas一行搞定但对学生理解ETL流程极有帮助。商业分析延伸对接地理编码API把CSV里的地址字段用高德地图API转成经纬度再用folium生成热力图。我用这个方法帮一家连锁奶茶品牌找到了上海租金性价比最高的5个开店盲区——脚本本身不提供API密钥但README.md里写了调用高德API的完整示例代码连requests.get()的参数都配好了。技术升级延伸平滑过渡到异步当单机QPS不够时我把requests换成httpxasyncio在保持解析逻辑不变的前提下把100页耗时从35分钟压缩到6分钟。核心改动只有三处async def fetch_page()、await asyncio.gather(*tasks)、BeautifulSoup(await response.aread(), html.parser)。这些升级路径在wjk.py的注释里都有标记比如# TODO: 支持async mode方便用户按需启用。最后分享一个小技巧每次抓取前先用脚本跑一个“探针URL”——比如https://www.dianping.com/search/keyword/1/0_测试看能否返回正常HTML。如果探针失败说明平台策略变了立刻停手而不是盲目扩大规模。爬虫工程师的核心素养不是写得多炫酷而是知道什么时候该停。这个脚本的设计哲学就是帮你把“知道该停”的判断点提前到第一次请求之前。本文还有配套的精品资源点击获取简介提供一套开箱即用的Python脚本专门用于从大众点评的搜索结果页和商户列表页批量提取公开可访问的信息包括店铺名称、详细地址、用户评分、评论总数、人均消费金额等结构化字段。核心代码由getData.py和wjk.py组成基于requests发起HTTP请求、BeautifulSoup解析HTML不依赖Selenium、无浏览器自动化操作也不涉及账号登录、滑块识别或复杂反爬绕过逻辑。配套README.md文档清晰说明运行步骤、参数配置及注意事项requirements.txt列出全部依赖项仅基础库无额外安装负担。已在Windows、Linux、macOS三大系统实测通过兼容Python 3.6及以上版本。适合需要快速获取基础商户信息用于教学演示、课程作业、毕设数据准备或初步市场分析的用户强调轻量、稳定、易读、易改——所有解析逻辑均有注释便于理解页面结构与数据定位方式。本文还有配套的精品资源点击获取