---
title: "2026年如何用 Python 抓取 Yelp 数据"
description: "了解如何使用 Python 和 BeautifulSoup 抓取 Yelp 数据，本文提供防屏蔽与解析策略的详细步骤。"
url: "https://marsproxies.cn/blog/scrape-yelp-data/"
---

[跳到主要内容](https://marsproxies.cn/blog/scrape-yelp-data/#page-content)

- [英语](https://marsproxies.com/blog/scrape-yelp-data/)
- [中文](https://marsproxies.cn/blog/scrape-yelp-data/)

[联系销售](https://marsproxies.cn/contact-sales/) [登录](https://dashboard.marsproxies.com/login/)

[注册](https://dashboard.marsproxies.com/register/)

[联系销售](https://marsproxies.cn/contact-sales/) [登录](https://dashboard.marsproxies.com/login/)

- [英语](https://marsproxies.com/blog/scrape-yelp-data/)
- [中文](https://marsproxies.cn/blog/scrape-yelp-data/)

[返回博客](https://marsproxies.cn/blog/) 2026年11月9日

# 2026年如何用 Python 抓取 Yelp 数据

[操作指南](https://marsproxies.cn/blog/category/how-to/)

\-

目录

1. [使用 Python 抓取 Yelp 数据的分步指南](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E4%BD%BF%E7%94%A8-python-%E6%8A%93%E5%8F%96-yelp-%E6%95%B0%E6%8D%AE%E7%9A%84%E5%88%86%E6%AD%A5%E6%8C%87%E5%8D%97)
2. [查找并检查 Yelp 商家信息页面](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E6%9F%A5%E6%89%BE%E5%B9%B6%E6%A3%80%E6%9F%A5-yelp-%E5%95%86%E5%AE%B6%E4%BF%A1%E6%81%AF%E9%A1%B5%E9%9D%A2)
3. [发送 HTTP 请求并解析 HTML](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E5%8F%91%E9%80%81-http-%E8%AF%B7%E6%B1%82%E5%B9%B6%E8%A7%A3%E6%9E%90-html)
4. [提取商家信息](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E6%8F%90%E5%8F%96%E5%95%86%E5%AE%B6%E4%BF%A1%E6%81%AF)
5. [抓取评论数据](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E6%8A%93%E5%8F%96%E8%AF%84%E8%AE%BA%E6%95%B0%E6%8D%AE)
6. [抓取 Yelp 搜索结果](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E6%8A%93%E5%8F%96-yelp-%E6%90%9C%E7%B4%A2%E7%BB%93%E6%9E%9C)
7. [将数据保存为 CSV 或 Excel 格式](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E5%B0%86%E6%95%B0%E6%8D%AE%E4%BF%9D%E5%AD%98%E4%B8%BA-csv-%E6%88%96-excel-%E6%A0%BC%E5%BC%8F)
8. [完整代码](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E5%AE%8C%E6%95%B4%E4%BB%A3%E7%A0%81)
9. [常见错误及解决方法](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E5%B8%B8%E8%A7%81%E9%94%99%E8%AF%AF%E5%8F%8A%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95)
10. [403 禁止访问错误](https://marsproxies.cn/blog/scrape-yelp-data/#b-403-%E7%A6%81%E6%AD%A2%E8%AE%BF%E9%97%AE%E9%94%99%E8%AF%AF)
11. [处理空响应或不完整响应](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E5%A4%84%E7%90%86%E7%A9%BA%E5%93%8D%E5%BA%94%E6%88%96%E4%B8%8D%E5%AE%8C%E6%95%B4%E5%93%8D%E5%BA%94)
12. [如何避免被封禁](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E5%A6%82%E4%BD%95%E9%81%BF%E5%85%8D%E8%A2%AB%E5%B0%81%E7%A6%81)
13. [轮换 IP 与代理](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E8%BD%AE%E6%8D%A2-ip-%E4%B8%8E%E4%BB%A3%E7%90%86)
14. [User-Agent 轮换与延迟设置](https://marsproxies.cn/blog/scrape-yelp-data/#b-user-agent-%E8%BD%AE%E6%8D%A2%E4%B8%8E%E5%BB%B6%E8%BF%9F%E8%AE%BE%E7%BD%AE)
15. [CAPTCHA 处理技巧](https://marsproxies.cn/blog/scrape-yelp-data/#b-captcha-%E5%A4%84%E7%90%86%E6%8A%80%E5%B7%A7)
16. [Yelp 抓取数据的实际使用场景](https://marsproxies.cn/blog/scrape-yelp-data/#b-yelp-%E6%8A%93%E5%8F%96%E6%95%B0%E6%8D%AE%E7%9A%84%E5%AE%9E%E9%99%85%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF)
17. [销售线索挖掘与本地商家调研](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E9%94%80%E5%94%AE%E7%BA%BF%E7%B4%A2%E6%8C%96%E6%8E%98%E4%B8%8E%E6%9C%AC%E5%9C%B0%E5%95%86%E5%AE%B6%E8%B0%83%E7%A0%94)
18. [情感分析与评论监测](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E6%83%85%E6%84%9F%E5%88%86%E6%9E%90%E4%B8%8E%E8%AF%84%E8%AE%BA%E7%9B%91%E6%B5%8B)
19. [抓取 Yelp 是否合法？](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E6%8A%93%E5%8F%96-yelp-%E6%98%AF%E5%90%A6%E5%90%88%E6%B3%95)
20. [Yelp 的服务条款](https://marsproxies.cn/blog/scrape-yelp-data/#b-yelp-%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%9D%A1%E6%AC%BE)
21. [开发者应考虑的道德问题](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E5%BC%80%E5%8F%91%E8%80%85%E5%BA%94%E8%80%83%E8%99%91%E7%9A%84%E9%81%93%E5%BE%B7%E9%97%AE%E9%A2%98)
22. [常见问题](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98)

\-

Yelp 是餐厅、商店、承包商、美容院等本地商家信息的重要来源之一。单条商家信息可能包含商家名称、地址、电话号码、营业时间、类别、评分、评论数量、价格区间、图片以及顾客评价。如果需要同时对比大量商家信息，手动收集很快就会变得不现实。

本指南将介绍如何使用 [Python](https://marsproxies.com/blog/python-web-scraping/)、Requests 和 BeautifulSoup 抓取 Yelp 数据，内容涵盖单条商家信息、评论、搜索结果页面、CSV 与 Excel 导出、常见错误、代理，以及负责任的数据抓取方式。

请注意，Yelp 页面结构会不断变化，因此本文给出的选择器仅作为起点，实际运行前可能需要更新。

## 使用 Python 抓取 Yelp 数据的分步指南

开始之前，请先安装本教程所需的库：使用 Requests 发送 HTTP 请求，使用 BeautifulSoup 解析 HTML，使用 pandas 保存结构化结果，使用 openpyxl 输出 Excel 文件。

```javascript
pip install requests beautifulsoup4 pandas openpyxl
```

浏览器的开发者工具也很有用：在 Chrome 或 Firefox 中打开 Yelp 页面，右键点击需要采集的元素，选择“检查”，查看周围的 HTML 结构。

尽量优先使用 data-testid、aria-label 或稳定的链接模式等有实际含义的属性，而不是 css-abc123 这类自动生成的类名，因为这类类名可能随时发生变化。

### 查找并检查 Yelp 商家信息页面

先从一个公开的商家信息页面入手。典型的商家页面通常包含名称、评分、评论数量、地址、电话号码、类别、营业时间等信息。

在编写选择器之前，先确定最终数据集需要哪些字段。一个简单的结构可以包含 name、category、rating、review\_count、address、phone 和 url。

更详细的项目还可以包含价格区间、营业时间、地理坐标或简短的设施列表。先确定好字段结构，可以避免解析器最终变成一堆互不相关的选择器。

另一个需要考虑的问题是将“发现阶段”与“详细信息采集阶段”分开：发现阶段负责确定每条商家信息的 URL 及基本元数据；详情阶段仅在需要更多细节时才访问具体的商家页面。这种两阶段的方式可以减少不必要的请求，使抓取 Yelp 数据的过程更易于调试。

如果您的目标是为竞品研究抓取 Yelp 数据，最好先从单条商家信息入手，确认解析器正常工作后，再添加分页或处理成百上千个 URL，这样调试起来会容易得多。

打开页面源代码，留意一些常见的规律：Yelp 通常会在 /biz/ 路径下暴露商家链接，通过无障碍标签展示评分，并在 JSON 或 JSON-LD 脚本标签中提供部分结构化信息。结构化数据尤其有用，因为它比 CSS 类名更不容易发生变化。

例如，HTML 中可能包含类似下面这样的脚本：

```markup
<script type = "application/ld+json" >
{
  "@type": "Restaurant",
  "name": "Example Restaurant",
  "aggregateRating": {
    "ratingValue": "4.5",
    "reviewCount": "125"
  }
}
</script >
```

并非每个页面的结构都相同，关键在于在选择选择器之前先检查实际页面。

### 发送 HTTP 请求并解析 HTML

接下来创建一个可复用的函数，用于下载页面并将响应转换为 BeautifulSoup 对象。

```python
import requests
from bs4 import BeautifulSoup
 
HEADERS = {
    "User-Agent" : (
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
        "AppleWebKit/537.36 (KHTML, like Gecko) "
        "Chrome/131.0.0.0 Safari/537.36"
    ) ,
    "Accept-Language" : "en-US,en;q=0.9" ,
}
 
def get_soup (url) :
    response = requests.get(
        url,
        headers=HEADERS,
        timeout= 20
    )
    response.raise_for_status( )
    return BeautifulSoup(response.text, "html.parser" )
```

请将下面的 URL 替换为您有权访问的商家页面：

```python
url = "https://www.yelp.com/biz/example-business"
soup = get_soup(url)
 
print (soup.title.get_text(strip= True ) if soup.title else "No title found" )
```

requests.get() 用于发送 HTTP 请求，raise\_for\_status() 则会在响应失败时抛出异常。随后 BeautifulSoup 会解析返回的 HTML，以便您使用 CSS 选择器和标签方法进行查找。

如果您需要的字段依赖 JavaScript 渲染，初始 HTML 中可能不会包含它。遇到这种情况，请先检查页面源代码；如果相关信息只有在渲染后才会出现，您可能需要使用 Playwright 或 Selenium 等浏览器自动化工具，而不能只依赖 Requests。

### 提取商家信息

从商家页面提取数据有两种实用方法：在存在结构化 JSON-LD 的情况下优先读取，再以 HTML 选择器作为备用方案。

下面的函数会遍历 JSON-LD 代码块，返回本地商家常见的相关字段。

```python
import json
 
def extract_json_ld (soup) :
    records = [ ]
 
    for script in soup.select( 'script[type="application/ld+json"]' ) :
        if not script.string:
            continue
 
        try :
            payload = json.loads(script.string)
        except json.JSONDecodeError:
            continue
 
        if isinstance (payload, list ) :
            records.extend(payload)
        elif isinstance (payload, dict ) :
            records.append(payload)
 
    for item in records:
        if not isinstance (item, dict ) :
            continue
 
        item_type = item.get( "@type" , "" )
        if isinstance (item_type, list ) :
            item_type = " " .join(item_type)
 
        if any (word in str (item_type) for word in [
            "LocalBusiness" , "Restaurant" , "Store" ,
            "FoodEstablishment" , "ProfessionalService"
        ] ) :
            rating = item.get( "aggregateRating" , { } ) or { }
            address = item.get( "address" , { } ) or { }
 
            return {
                "name" : item.get( "name" ) ,
                "rating" : rating.get( "ratingValue" ) ,
                "review_count" : rating.get( "reviewCount" ) ,
                "phone" : item.get( "telephone" ) ,
                "price_range" : item.get( "priceRange" ) ,
                "street" : address.get( "streetAddress" ) ,
                "city" : address.get( "addressLocality" ) ,
                "region" : address.get( "addressRegion" ) ,
                "postal_code" : address.get( "postalCode" ) ,
            }
    return { }
```

运行方式如下：

```python
business = extract_json_ld(soup)
print (business)
```

这是一个有用的第一层处理方式，不过结构化标记可能无法覆盖所有字段。如果需要类别、其他属性或提供的服务等信息，您可能还需要使用 HTML 选择器。

一个简单的兜底辅助函数可以避免元素缺失导致脚本崩溃：

```python
def text_or_none (element) :
    return element.get_text( " " , strip= True ) if element else None
 
name = text_or_none(soup.select_one( "h1" ) )
rating_node = soup.select_one( '[aria-label*="star rating"]' )
 
rating = rating_node.get( "aria-label" ) if rating_node else None
```

在抓取 Yelp 数据时，只要结构化选择器可行，就应尽量避免硬编码冗长的自动生成类名。如果某个字段在所有商家信息中都突然变成 None，请先重新检查页面，而不要直接认定请求失败。

具体需要采集哪些商家数据，取决于您的项目：

- **用于获客的数据集**可能侧重于公司名称、类别、电话号码和地址

* **市场调研**可能需要评分、评论数量、价格水平和餐厅相关数据

- **目录监控类项目**可能更关注营业时间、歇业状态或所提供的服务

### 抓取评论数据

评论数据的抓取难度更高，因为页面布局可能发生变化，部分内容还可能是动态加载的。在抓取 Yelp 评论之前，请先检查返回的 HTML 中是否真的包含您需要的评论文本。

一种更稳妥的解析方式是先找到评论容器，再在每个容器内部进行查找：

```python
def extract_reviews (soup) :
    reviews = [ ]
 
    containers = soup.select(
        '[data-testid="review"], '
        'li[class*="review"]'
    )
 
    for container in containers:
        text_node = container.select_one(
            'p[class*="comment"], '
            '[data-testid="review-comment"]'
        )
        rating_node = container.select_one(
            '[aria-label*="star rating"]'
        )
        date_node = container.select_one(
            'span[class*="date"], '
            'time'
        )
 
        review = {
            "text" : text_or_none(text_node) ,
            "rating" : (
                rating_node.get( "aria-label" )
                if rating_node else None
            ) ,
            "date" : text_or_none(date_node) ,
        }
 
        if review[ "text" ] :
            reviews.append(review)
 
    return reviews
```

这会生成一个包含评论数据的字典列表。如果您的使用场景需要，也可以添加作者姓名或其他字段，但需确保这样做是合适的。

这里有一个重要的限制：普通的 Requests 响应不一定包含完整渲染浏览器中所看到的全部评论内容。如果返回的 HTML 不完整，请先确认您拿到的是正常页面，而不是验证页面或错误页面，然后再检查是否需要 JavaScript 渲染。

另外请注意，顾客评论属于用户生成内容。请仅在确有需要时采集信息，避免借此生成不必要的用户画像，并事先了解相关网站的服务条款以及适用的隐私和版权法律。

### 抓取 Yelp 搜索结果

如果您手头还没有商家 URL 列表，搜索结果页面会很有用。例如，您可以搜索芝加哥的水管工、波士顿的咖啡馆或奥斯汀的餐厅，并采集页面上可见的商家信息。

Yelp 的搜索 URL 通常包含搜索词和地点，简化后的示例如下：

```javascript
https : / /www.yelp.com/search?find_desc=coffee&find_loc=Boston%2C+ MA
```

您可以使用 Requests 安全地构建该 URL：

```python
from urllib.parse import urlencode
 
params = {
    "find_desc" : "coffee" ,
    "find_loc" : "Boston, MA" ,
}
 
search_url = "https://www.yelp.com/search?" + urlencode(params)
search_soup = get_soup(search_url)
```

接下来定位自然搜索结果卡片。用于测试的属性通常比自动生成的 CSS 类名更可靠：

```python
from urllib.parse import urljoin
 
def extract_search_results (soup) :
    results = [ ]
    seen = set ( )
 
    cards = soup.select( '[data-testid="serp-ia-card"]' )
 
    for card in cards:
        link = card.select_one( 'a[href^="/biz/"]' )
        if not link:
            continue
 
        href = link.get( "href" , "" ) .split( "?" ) [ 0 ]
        if not href or href in seen:
            continue
 
        seen.add(href)
 
        rating_node = card.select_one( '[aria-label*="star rating"]' )
        text = card.get_text( " " , strip= True )
 
        results.append( {
            "name" : link.get_text( " " , strip= True ) ,
            "url" : urljoin( "https://www.yelp.com" , href) ,
            "rating" : (
                rating_node.get( "aria-label" )
                if rating_node else None
            ) ,
            "card_text" : text,
        } )
 
    return results
```

运行：

```python
results = extract_search_results(search_soup)
 
for result in results:
    print (result)
```

这样可以获得以下信息：

- 商家名称

* URL

- 评分（如果有）

* 卡片中可见的文本

在此基础上，您可以进一步完善类别、社区、评论数量或价格区间等字段的选择器。

如果需要抓取多页搜索结果，请检查实际的分页规律，而不要凭猜测行事，因为 Yelp 的页面布局和 URL 参数都可能发生变化。请在各页请求之间加入较保守的延迟，并在某一页不再返回新商家信息时及时停止。

分页逻辑还必须确保对条目进行去重。由于推广商家信息、结果顺序变化、搜索条件重叠等多种原因，同一条商家信息可能会反复出现。

去重时建议使用 /biz/ 这样的规范 URL 或其他唯一标识符，而不要只依赖名称，因为不同商家也可能使用相同的名称。

对于较大的数据文件，建议在每完成一页后就保存进度。即使脚本在中途停止，也无需重新下载之前的页面，可以直接从中断处继续。

```python
import random
import time
 
time.sleep(random.uniform( 3 , 6 ) )
```

抓取 Yelp 数据的程序应优先考虑稳定性，而不是速度。短时间内发送大量请求会产生更多错误，给网站带来不必要的负载，并增加访问被限制的可能性。

### 将数据保存为 CSV 或 Excel 格式

有了字典列表之后，使用 pandas 导出数据会非常简单。

导出为 CSV：

```python
import pandas as pd
 
df = pd.DataFrame(results)
df.to_csv( "yelp_results.csv" , index= False , encoding= "utf-8-sig" )
```

导出为 Excel：

```javascript
df. to_excel ( "yelp_results.xlsx" , index=False)
```

商家详情或评论数据也可以用同样的方式处理：

```javascript
reviews_df = pd. DataFrame ( extract_reviews (soup) )
reviews_df. to_csv ( "yelp_reviews.csv" , index=False)
```

对于较大的数据集，CSV 通常是最简单的格式，而 Excel 则更便于人工核查，也方便与不熟悉技术的同事共享。

保存之前，建议先对数据进行规范化处理：将评分字符串转换为数字，去掉评论数量中的"reviews"字样，统一电话号码格式，并将城市、地区和邮政编码拆分到独立的列中。结构清晰的数据后续分析起来会容易得多。

此外，建议添加 source\_url、collected\_at、status 等运维字段。当记录来自不同批次的运行时，这些字段会让问题排查变得容易得多：如果某个值缺失，您可以借此区分“该商家信息本身没有公开此字段”与“本次运行解析失败”这两种情况。对于需要反复进行的研究，时间戳还能帮助您对比不同快照、识别变化，而不是盲目覆盖旧记录。

不要假设一开始采集到的数据就是干净的，不同商家信息中记录的类别名称、地址、营业时间和价格信息可能存在差异。数据清洗应放在后续环节处理，而不是让解析器承担所有清洗工作，这样也更便于测试。

### 完整代码

下面是一个整合了主要步骤的简洁示例：请求商家页面，提取结构化的商家信息和评论数据，然后保存结果。

```python
import json
import time
import random
import requests
import pandas as pd
from bs4 import BeautifulSoup
 
HEADERS = {
    "User-Agent" : (
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
        "AppleWebKit/537.36 (KHTML, like Gecko) "
        "Chrome/131.0.0.0 Safari/537.36"
    ) ,
    "Accept-Language" : "en-US,en;q=0.9" ,
}
 
def get_soup (url, proxies= None ) :
    response = requests.get(
        url,
        headers=HEADERS,
        proxies=proxies,
        timeout= 20
    )
    response.raise_for_status( )
    return BeautifulSoup(response.text, "html.parser" )
 
def text_or_none (element) :
    return element.get_text( " " , strip= True ) if element else None
 
def extract_json_ld (soup) :
    records = [ ]
 
    for script in soup.select( 'script[type="application/ld+json"]' ) :
        if not script.string:
            continue
        try :
            payload = json.loads(script.string)
        except json.JSONDecodeError:
            continue
 
        if isinstance (payload, list ) :
            records.extend(payload)
        elif isinstance (payload, dict ) :
            records.append(payload)
 
    for item in records:
        if not isinstance (item, dict ) :
            continue
 
        item_type = str (item.get( "@type" , "" ) )
        if any (x in item_type for x in [
            "LocalBusiness" , "Restaurant" ,
            "Store" , "FoodEstablishment"
        ] ) :
            rating = item.get( "aggregateRating" , { } ) or { }
            address = item.get( "address" , { } ) or { }
 
            return {
                "name" : item.get( "name" ) ,
                "rating" : rating.get( "ratingValue" ) ,
                "review_count" : rating.get( "reviewCount" ) ,
                "phone" : item.get( "telephone" ) ,
                "price_range" : item.get( "priceRange" ) ,
                "street" : address.get( "streetAddress" ) ,
                "city" : address.get( "addressLocality" ) ,
                "region" : address.get( "addressRegion" ) ,
                "postal_code" : address.get( "postalCode" ) ,
            }
 
    return { }
 
def extract_reviews (soup) :
    data = [ ]
 
    for container in soup.select(
        '[data-testid="review"], li[class*="review"]'
    ) :
        text_node = container.select_one(
            'p[class*="comment"], [data-testid="review-comment"]'
        )
        rating_node = container.select_one(
            '[aria-label*="star rating"]'
        )
        date_node = container.select_one(
            'span[class*="date"], time'
        )
 
        text = text_or_none(text_node)
        if not text:
            continue
 
        data.append( {
            "text" : text,
            "rating" : (
                rating_node.get( "aria-label" )
                if rating_node else None
            ) ,
            "date" : text_or_none(date_node) ,
        } )
 
    return data
 
url = "https://www.yelp.com/biz/example-business"
soup = get_soup(url)
business = extract_json_ld(soup)
reviews = extract_reviews(soup)
 
pd.DataFrame( [business] ) .to_csv(
    "business.csv" , index= False , encoding= "utf-8-sig"
)
pd.DataFrame(reviews) .to_csv(
    "reviews.csv" , index= False , encoding= "utf-8-sig"
)
 
time.sleep(random.uniform( 3 , 6 ) )
 
print ( "Business:" , business)
print ( f"Reviews collected:  { len (reviews) } " )
```

这只是一个可运行的原型，不应直接作为抓取 Yelp 数据的最终实现。每次运行前，请检查实际的 HTML、验证单个 URL、确认字段返回正确，并加入日志记录，以便及时发现页面布局的变化。

值得一提的是，Python 及其各类库并不局限于 Yelp。Python 是一种强大的工具，也可以用于[Google Maps](https://marsproxies.com/blog/scrape-google-maps/)、Amazon 等许多其他网站。

## 常见错误及解决方法

即使是一段简短的脚本，也可能因访问限制、页面改版、字段缺失或网络问题而运行失败。最有效的调试习惯是：在修改解析器之前，先检查 HTTP 状态码和响应正文的开头部分。

错误处理机制应围绕 requests 层来设计，而不是在代码各处都套用 try/except。网络超时、服务器临时故障、页面解析失败、字段缺失，这些都是不同类型的问题，应分别记录。

适合生产环境的脚本可以配置日志机制，将 URL、状态码、异常类型和重试次数记录到文件中。

请限制重试次数。对于临时性的 502 错误或超时，可以在等待一段时间后重试，但对 403 错误反复重试多次通常没有任何帮助。

### 403 禁止访问错误

403 Forbidden 响应表示服务器已收到您的请求，但拒绝提供该网页。抓取 Yelp 时，由于自动化请求过多、流量模式异常、缺少请求头或使用了信誉较差的 IP 地址，都可能导致出现 403 禁止访问的响应。

首先确认该 URL 在浏览器中能否正常打开，并检查代码发送请求的速度。使用合适的 User-Agent、设置超时时间、降低请求速度；一旦收到 403 响应，就不要再反复请求同一页面。

您还可以添加简单的日志记录：

```python
response = requests.get(url, headers=HEADERS, timeout= 20 )
print (response.status_code)
print (response.url)
print (response.text[ : 500 ] )
```

如果收到的是拒绝访问页面或验证页面，问题并不出在解析器上。不断修改 BeautifulSoup 选择器并不能解决被拦截的 HTTP 响应问题。

### 处理空响应或不完整响应

有时响应状态是 200 OK，但预期字段却缺失。这通常源于以下四种原因之一：选择器已失效、内容由 JavaScript 渲染生成、页面版本不同，或者返回的并非您预期的常规页面。

在提取数值之前添加检查：

```python
if len (response.text) < 1000 :
    print ( "Unexpectedly short response" )
```

调试时保存 HTML：

```typescript
with open ( "debug.html" , "w" , encoding= "utf-8" ) as file:
    file. write (response.text)
```

在浏览器中打开 debug.html，搜索商家名称或评论文本。如果该值存在，请更新选择器；如果不存在，则需排查渲染或访问问题。

同时，解析器的设计应能容忍字段缺失的情况。真实的商家数据并不统一：有的商家信息包含电话号码和价格区间，有的则没有。返回 None 比直接终止整个任务更合理。

2026年稳定抓取 Yelp 本地商家数据

[获取住宅代理](https://dashboard.marsproxies.com/products/ultra-residential-proxies#buy-now)

## 如何避免被封禁

大规模抓取产生的流量远高于正常浏览，这会触发速率限制甚至反机器人机制。目标不应是让网站不堪重负或瘫痪，而应是减少请求数量、合理分散请求，并在有官方 API 的情况下优先使用 API。

良好的请求策略意味着可预测性。尽量使用 requests.Session()，缓存已抓取过的页面，在请求之间加入暂停，并将并发数控制在较低水平。

如果您需要每天更新数据集，建议只更新可能发生变化的记录，而不是每次都从头抓取。这种方式能在不过度依赖反检测技术的情况下保持更好的稳定性。

监控同样重要。请持续跟踪请求成功率、平均响应大小、空记录数量以及解析错误率。提取字段数量的明显下降，往往在最终数据集反映出问题之前，就已经提示页面结构发生了变化。

### 轮换 IP 与代理

使用代理时，请求会经由一个额外的 IP 地址转发。在网络爬取中，代理可用于将允许的请求分散发送，而不是全部从同一台设备发出。

例如，Requests 库支持这样配置代理：

```typescript
PROXY_URL = "http://username:password@host:port"
 
proxies = {
    "http" : PROXY_URL ,
    "https" : PROXY_URL ,
}
 
soup = get_soup (url, proxies=proxies)
```

对于涉及本地商家的地理敏感型调研，[住宅代理](https://marsproxies.com/proxies/residential-proxies/)还可以提供与您所研究地理市场相匹配的 IP，这在页面内容因地区而异时会很有用。

不过，轮换 IP 并不代表您获得了访问网站所禁止内容的权限。如果某个页面持续拒绝自动化访问，请停止操作，查看网站规则，或改用获得授权的数据来源。

### User-Agent 轮换与延迟设置

User-Agent 用于告知服务器请求声称使用的浏览器和操作系统。有些抓取脚本会轮换 User-Agent，但如果每次请求都随机更换该请求头，反而会显得更不自然，而非更真实。

更好的做法是使用一小组有效的浏览器请求头，并搭配保守的延迟设置。例如：

```javascript
USER_AGENTS = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
    "AppleWebKit/537.36 (KHTML, like Gecko) "
    "Chrome/131.0.0.0 Safari/537.36" ,
 
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
    "AppleWebKit/605.1.15 (KHTML, like Gecko) "
    "Version/18.1 Safari/605.1.15" ,
]
```

然后在一次会话中选定其中一组，并在页面请求之间加入暂停：

```python
import random
import time
 
headers = { "User-Agent" : random.choice(USER_AGENTS) }
time.sleep(random.uniform( 3 , 7 ) )
```

延迟设置既能降低负载，也让重试行为更易于控制。对于耗时较长的任务，可加入指数退避机制，使失败请求的等待时间逐步延长，而不是立即重试。

### CAPTCHA 处理技巧

出现 CAPTCHA 往往明确表明网站希望当前流量停止，或要求证明请求由真人完成。请不要将脚本设计为不断尝试绕过 CAPTCHA。

正确的做法是：识别验证页面、停止抓取流程、降低每秒请求数，并确认是否存在官方 API 或授权的数据提供商可提供相同的 Yelp 数据。您也可以将人工处理方式纳入有监督的工作流程中。

一个简单的检测逻辑可以用于查找常见的验证页面文本：

```typescript
html_lower = response.text. lower ( )
 
if "captcha" in html_lower or "verify you are human" in html_lower:
    raise RuntimeError ( "Challenge page detected; stopping the job." )
```

相比构建一个不断尝试突破拦截的升级循环，这种方式更安全，也更易于维护。

## Yelp 抓取数据的实际使用场景

抓取 Yelp 数据的价值，不在于您采集了多少页面，而在于您想回答什么问题。请在编写抓取脚本之前先确定所需字段，避免采集不必要的信息。

### 销售线索挖掘与本地商家调研

公开的店铺信息可以帮助团队研究市场、发现潜在商机。例如，您可以针对某个城市采集商家名称、类别、所在街区、公开电话号码、评分以及评论数量。

随后可按类别或地区对这些商家数据进行筛选。面向餐饮行业的供应商可以比较哪些街区拥有较多评分较高的独立商户；软件公司则可以调研某个细分领域内的本地商家，并用公开可见的店铺信息来丰富现有的潜在客户名单。

关键在于保持数据集的相关性。不要仅因为某项信息技术上可见就去采集个人信息，也不要假设抓取到的联系方式就自动允许进行未经请求的营销推广。相关的营销与隐私法规依然适用。

### 情感分析与评论监测

评论分析可以揭示数字评分无法体现的深层主题。例如，一家餐厅的评分为 4.2 分，可能在食品质量方面持续获得正面评价，同时在配送时间方面却收到不少差评。

在提取数据之后，基础的自然语言处理可以将评论归类为正面、负面或中性情感，或随时间跟踪关键词变化。竞品调研还可以揭示顾客最看重哪些功能。

如果您抓取 Yelp 评论用于分析，应相应地控制好工作范围。使用评论全文可能涉及版权和技术问题，不应大量复制整段评论内容；不过，基于数量统计和主题归纳仍可以完成大量有价值的分析。

## 抓取 Yelp 是否合法？

网络爬取并不受单一统一规则约束。一个项目是否合法，取决于所在司法辖区、所采集信息的类型、访问方式、数据用途以及相关合同条款。

本节内容仅为一般性信息，不构成法律建议。对于商业项目或大规模抓取项目，在正式执行前进行法律审查是值得的。

### Yelp 的服务条款

Yelp 的服务条款禁止使用机器人、爬虫、搜索/数据检索工具及其他自动化手段来访问、获取、复制、抓取或索引其服务或内容，除非 Yelp 明确许可。Yelp 的商业条款中也包含针对自动化抓取和数据提取的限制。

这意味着，一个技术上可行的脚本并不代表自动获得许可。在抓取 Yelp 之前，请阅读适用于您账户、所在地区及计划用途的条款，并留意 Yelp 提供的任何授权说明或机器可读规则。

Yelp 还提供官方的开发者 API。目前 Yelp 的文档将常见的 Fusion 端点纳入 Yelp Places API 中，其中包括商家搜索和商家详情；评论访问仅限于摘要内容，具体取决于所适用的套餐。

如果该 API 能提供您所需的字段，通常是更简洁的选择，因为您可以直接获得结构化的响应，无需维护 HTML 选择器。

### 开发者应考虑的道德问题

良好的抓取习惯始于最小化原则：只获取所需字段、采用谨慎的请求节奏、通过缓存请求来避免重复下载页面，并在网站明确表示应停止自动化访问时及时退出。

同时也要保护好已存储的信息。评论文本、资料信息和联系方式，单独来看或许无害，但一旦汇总成大规模数据集，就可能引发隐私或法律问题。请设定数据保留期限、限制访问权限，并删除不必要的字段。

最后，请将抓取的技术能力与是否获得许可区分开来。代理、浏览器自动化和解析工具本身都是中立的技术手段，绝不应成为不遵守网站准则和限制的理由。

对于正在学习抓取 Yelp 数据或希望构建 Yelp 抓取工具的开发者来说，最有效的做法是：先在获得授权的小范围样本上进行测试，针对页面结构的意外变化编写防御逻辑，只采集必要的最小数据量，并在 Yelp API 能满足需求时优先使用该 API。

## 常见问题

Yelp 是否允许数据抓取？

Yelp 的服务条款通常禁止自动化抓取行为，除非 Yelp 明确允许；在自动采集数据前，请查阅其最新条款、robots.txt 规则以及任何适用的 API 选项。

Yelp 是否提供官方 API？

是的，Yelp 提供官方开发者 API，可用于商家搜索和商家信息查询；目前的 Yelp Places API 文档显示，符合条件的套餐还能获取有限的点评摘录。

能否抓取 Yelp 的点评数据？

理论上，只要数据可访问，这些内容在技术上是可解析的；但 Yelp 的条款明确规定，由于点评属于用户生成内容，不得对其进行自动化抓取。

[了解更多](https://dashboard.marsproxies.com/register/)

\-

作者

[Dalius Pamedytis 软件工程师](https://marsproxies.cn/blog/authors/dalius-pamedytis/)

目录

1. [使用 Python 抓取 Yelp 数据的分步指南](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E4%BD%BF%E7%94%A8-python-%E6%8A%93%E5%8F%96-yelp-%E6%95%B0%E6%8D%AE%E7%9A%84%E5%88%86%E6%AD%A5%E6%8C%87%E5%8D%97)
2. [查找并检查 Yelp 商家信息页面](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E6%9F%A5%E6%89%BE%E5%B9%B6%E6%A3%80%E6%9F%A5-yelp-%E5%95%86%E5%AE%B6%E4%BF%A1%E6%81%AF%E9%A1%B5%E9%9D%A2)
3. [发送 HTTP 请求并解析 HTML](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E5%8F%91%E9%80%81-http-%E8%AF%B7%E6%B1%82%E5%B9%B6%E8%A7%A3%E6%9E%90-html)
4. [提取商家信息](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E6%8F%90%E5%8F%96%E5%95%86%E5%AE%B6%E4%BF%A1%E6%81%AF)
5. [抓取评论数据](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E6%8A%93%E5%8F%96%E8%AF%84%E8%AE%BA%E6%95%B0%E6%8D%AE)
6. [抓取 Yelp 搜索结果](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E6%8A%93%E5%8F%96-yelp-%E6%90%9C%E7%B4%A2%E7%BB%93%E6%9E%9C)
7. [将数据保存为 CSV 或 Excel 格式](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E5%B0%86%E6%95%B0%E6%8D%AE%E4%BF%9D%E5%AD%98%E4%B8%BA-csv-%E6%88%96-excel-%E6%A0%BC%E5%BC%8F)
8. [完整代码](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E5%AE%8C%E6%95%B4%E4%BB%A3%E7%A0%81)
9. [常见错误及解决方法](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E5%B8%B8%E8%A7%81%E9%94%99%E8%AF%AF%E5%8F%8A%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95)
10. [403 禁止访问错误](https://marsproxies.cn/blog/scrape-yelp-data/#b-403-%E7%A6%81%E6%AD%A2%E8%AE%BF%E9%97%AE%E9%94%99%E8%AF%AF)
11. [处理空响应或不完整响应](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E5%A4%84%E7%90%86%E7%A9%BA%E5%93%8D%E5%BA%94%E6%88%96%E4%B8%8D%E5%AE%8C%E6%95%B4%E5%93%8D%E5%BA%94)
12. [如何避免被封禁](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E5%A6%82%E4%BD%95%E9%81%BF%E5%85%8D%E8%A2%AB%E5%B0%81%E7%A6%81)
13. [轮换 IP 与代理](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E8%BD%AE%E6%8D%A2-ip-%E4%B8%8E%E4%BB%A3%E7%90%86)
14. [User-Agent 轮换与延迟设置](https://marsproxies.cn/blog/scrape-yelp-data/#b-user-agent-%E8%BD%AE%E6%8D%A2%E4%B8%8E%E5%BB%B6%E8%BF%9F%E8%AE%BE%E7%BD%AE)
15. [CAPTCHA 处理技巧](https://marsproxies.cn/blog/scrape-yelp-data/#b-captcha-%E5%A4%84%E7%90%86%E6%8A%80%E5%B7%A7)
16. [Yelp 抓取数据的实际使用场景](https://marsproxies.cn/blog/scrape-yelp-data/#b-yelp-%E6%8A%93%E5%8F%96%E6%95%B0%E6%8D%AE%E7%9A%84%E5%AE%9E%E9%99%85%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF)
17. [销售线索挖掘与本地商家调研](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E9%94%80%E5%94%AE%E7%BA%BF%E7%B4%A2%E6%8C%96%E6%8E%98%E4%B8%8E%E6%9C%AC%E5%9C%B0%E5%95%86%E5%AE%B6%E8%B0%83%E7%A0%94)
18. [情感分析与评论监测](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E6%83%85%E6%84%9F%E5%88%86%E6%9E%90%E4%B8%8E%E8%AF%84%E8%AE%BA%E7%9B%91%E6%B5%8B)
19. [抓取 Yelp 是否合法？](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E6%8A%93%E5%8F%96-yelp-%E6%98%AF%E5%90%A6%E5%90%88%E6%B3%95)
20. [Yelp 的服务条款](https://marsproxies.cn/blog/scrape-yelp-data/#b-yelp-%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%9D%A1%E6%AC%BE)
21. [开发者应考虑的道德问题](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E5%BC%80%E5%8F%91%E8%80%85%E5%BA%94%E8%80%83%E8%99%91%E7%9A%84%E9%81%93%E5%BE%B7%E9%97%AE%E9%A2%98)
22. [常见问题](https://marsproxies.cn/blog/scrape-yelp-data/#b-%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98)

分类

- [产品动态](https://marsproxies.cn/blog/category/product-news/)

  [5](https://marsproxies.cn/blog/category/product-news/)
- [产品对比](https://marsproxies.cn/blog/category/comparisons/)

  [11](https://marsproxies.cn/blog/category/comparisons/)
- [反检测解决方案](https://marsproxies.cn/blog/category/antidetect-solution/)

  [3](https://marsproxies.cn/blog/category/antidetect-solution/)
- [操作指南](https://marsproxies.cn/blog/category/how-to/)

  [124](https://marsproxies.cn/blog/category/how-to/)
- [球鞋抢购机器人](https://marsproxies.cn/blog/category/sneaker-bots/)

  [2](https://marsproxies.cn/blog/category/sneaker-bots/)
- [资讯](https://marsproxies.cn/blog/category/insights/)

  [91](https://marsproxies.cn/blog/category/insights/)

## 相关文章

[操作指南](https://marsproxies.cn/blog/category/how-to/)

### [YouTube 400 错误：含义及修复方法](https://marsproxies.cn/blog/youtube-error-400/)

YouTube 400 错误可能出现在 Android、iPhone、桌面端和电视端，了解其成因以及如何修复“服务器出现问题 \[400]”提示。

[Lukas Tilkevicius 增长与合作经理](https://marsproxies.cn/blog/authors/lukas-tilkevicius/)

2026年11月2日

[操作指南](https://marsproxies.cn/blog/category/how-to/)

### [Twitter 数据抓取 API：实用工具与使用方法](https://marsproxies.cn/blog/twitter-scraper-api/)

了解 Twitter 数据抓取 API 的工作原理，比较各类工具，并通过实用示例、技巧和实践经验，掌握如何抓取 Twitter 数据。

[Dalius Pamedytis 软件工程师](https://marsproxies.cn/blog/authors/dalius-pamedytis/)

2026年10月29日

[操作指南](https://marsproxies.cn/blog/category/how-to/)

### [如何在美国观看日本电视：2026年指南](https://marsproxies.cn/blog/watch-japanese-tv-in-usa/)

了解在美国观看日本电视的多种方法，包括免费流媒体平台、VPN 设置指南和订阅服务。

[Lukas Tilkevicius 增长与合作经理](https://marsproxies.cn/blog/authors/lukas-tilkevicius/)

2026年10月28日
