# OpenRice 爬蟲｜香港餐廳、評分、菜式、地區、食評數一鍵匯出（免 API） (`claude_code_reviewer/openrice-scraper`) Actor

免登入抓 OpenRice 香港餐廳：名稱、地區、菜式、評分、食評數、地址、電話與圖片，輸出 JSON／CSV／Excel。餐飲選址、市場調查、競品分析必備。

- **URL**: https://apify.com/claude\_code\_reviewer/openrice-scraper.md
- **Developed by:** [Chad](https://apify.com/claude_code_reviewer) (community)
- **Categories:** Agents, Travel, Social media
- **Stats:** 7 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 搜尋餐廳

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## OpenRice 爬蟲｜香港餐廳資料一鍵下載

從 [OpenRice](https://www.openrice.com/zh/hongkong) 抓取香港餐廳搜尋列表資料，包含餐廳名稱、菜式、地區、評分、食評數量、地址、電話、圖片網址等完整欄位。

- **走公開 JSON API**，不用登入、不用 token、不用瀏覽器
- **唯一穩定競品**：Apify Store 上唯一的競品已長期 UNDER\_MAINTENANCE、30/38 runs timeout
- **批量關鍵字**：支援多個關鍵字並行搜尋，地區 / 菜式 ID 過濾
- **結構化輸出**：snake\_case 欄位，缺值補 `null`，一律附 ISO 8601 時間戳

***

### 輸出欄位

| 欄位 | 類型 | 說明 | 版本 |
|---|---|---|---|
| `poi_id` | string | OpenRice 餐廳唯一 ID | v1.0 |
| `name` | string | null | 餐廳中文名稱 | v1.0 |
| `cuisine` | string\[] | null | 菜式陣列（如 `["日本菜", "壽司/刺身"]`） | v1.0 |
| `district` | string | null | 地區中文名稱（如「銅鑼灣」） | v1.0 |
| `price_range` | string | null | 價位：`$` / `$$` / `$$$` / `$$$$` | v1.0 |
| `rating` | number | null | OpenRice 整體評分（如 `3.87`） | v1.0 |
| `review_count` | integer | null | 食評數量 | v1.0 |
| `bookmark_count` | integer | null | 收藏人數 | v1.0 |
| `address` | string | null | 餐廳地址（中文） | v1.0 |
| `phone` | string | null | 電話號碼（第一個） | v1.0 |
| `opening_hours` | string | null | 營業時間 JSON 字串（v1.1 改為易讀格式） | v1.0 |
| `image_urls` | string\[] | 餐廳圖片 URL 陣列（無圖片為 `[]`） | v1.0 |
| `restaurant_url` | string | OpenRice 餐廳頁面完整 URL | v1.0 |
| `source_mode` | string | 資料來源模式（目前為 `"search"`） | v1.0 |
| `source_query` | string | 觸發此筆資料的搜尋關鍵字 | v1.0 |
| `scraped_at` | string | 抓取時間戳（ISO 8601，UTC） | v1.0 |

***

### 模式

| mode | 輸入 | 產出 | 計費事件 |
|---|---|---|---|
| `search`（v1.0） | `keywords[]` + 可選 `district` / `cuisine` 過濾 | 搜尋列表結果 | `search-listing`（每筆 $0.002） |
| `detail`（v1.1，開發中） | `restaurantIds[]` 或 `restaurantUrls[]` | 餐廳完整詳情 | `product-detail` |

***

### 輸入參數

| 參數 | 類型 | 必填 | 預設 | 說明 |
|---|---|---|---|---|
| `keywords` | string\[] | ✓ | — | 搜尋關鍵字（餐廳名稱/菜式），最多 50 個 |
| `bulkInput` | string | — | — | 一行一個關鍵字，自動合併到 `keywords` |
| `district` | string | — | — | 地區 ID（如 `1019` = 銅鑼灣，見下方說明） |
| `cuisine` | string | — | — | 菜式 ID（如 `2009` = 日本菜，見下方說明） |
| `maxItems` | integer | — | `50` | 每關鍵字最多筆數（1–500） |
| `proxyConfiguration` | object | — | 不使用 | Apify Proxy 或自訂 proxy |

#### 常用地區 ID（district）

| districtId | 地區 |
|---|---|
| 1999 | 香港島（全區） |
| 1019 | 銅鑼灣 |
| 1001 | 上環 / 中環 |
| 2999 | 九龍（全區） |
| 2010 | 旺角 |
| 2001 | 尖沙咀 |
| 3999 | 新界（全區） |

完整列表可呼叫 `GET https://www.openrice.com/api/v2/metadata/region/all?uiLang=zh&uiCity=hongkong` 取得。

#### 常用菜式 ID（cuisine）

| cuisineId | 菜式 |
|---|---|
| 1004 | 港式 |
| 2009 | 日本菜 |
| 4000 | 西式 |
| 1007 | 中式 |
| 2001 | 韓國菜 |

***

### 輸入範例

#### 1. 搜尋壽司（預設設定）

```json
{
    "keywords": ["壽司"],
    "maxItems": 20
}
```

#### 2. 中環燒烤篩選（上環/中環地區，districtId=1001）

```json
{
    "keywords": ["燒烤"],
    "district": "1001",
    "maxItems": 20
}
```

#### 3. 多關鍵字批量搜尋

```json
{
    "keywords": ["日本料理", "韓國烤肉"],
    "maxItems": 50
}
```

#### 4. 旺角日本菜（地區 + 菜式雙重過濾）

```json
{
    "keywords": ["壽司"],
    "district": "2010",
    "cuisine": "2009",
    "maxItems": 30
}
```

#### 5. 批量輸入多關鍵字

```json
{
    "bulkInput": "壽司\n燒烤\n火鍋\n茶餐廳\n點心",
    "maxItems": 30
}
```

***

### 注意事項

- **穩定性賣點**：唯一競品長期 UNDER\_MAINTENANCE（30/38 runs timeout），本 Actor 走純 JSON API、無瀏覽器、指數退避重試，跑得完才算贏
- **計費時機**：`Actor.charge()` 只在資料成功 push 到 dataset 之後才呼叫，中途失敗不計費
- **連續空頁偵測**：連續 5 頁拿不到新資料自動停止，不空轉燒錢
- **`detail` 模式（v1.1）**：OpenRice 的 POI 詳情 API 端點目前未公開，probe 全部回 404；待找到或逆向工程後加入

***

### 常見問題 FAQ

**Q: 為什麼有些欄位是 `null`？**\
A: OpenRice 部分餐廳資料不完整（如沒有電話、未填地址），本 Actor 一律補 `null` 而不省略欄位，確保每筆資料結構一致。

**Q: `opening_hours` 是什麼格式？**\
A: v1.0 輸出 JSON 字串，包含每天的 `dayOfWeek`（1=日、2=一...7=六）、`period1Start`、`period1End`、`is24hr`、`isClose` 等欄位。v1.1 將改為人類可讀的格式。

**Q: 可以只搜尋特定地區嗎？**\
A: 可以，在 `district` 填入 districtId（如 `1019` = 銅鑼灣）。完整 districtId 清單可從 metadata API 取得。

**Q: 支援 proxy 嗎？**\
A: 支援 Apify Proxy 或自訂 proxy，預設不使用（直連已可正常爬取）。

**Q: `image_urls` 是否包含所有圖片？**\
A: 包含餐廳主圖（doorPhoto）及搜尋列表中回傳的最新圖片（通常 3–5 張）。完整相簿需 detail 模式（v1.1）。

**Q: 可以抓食評內容嗎？**\
A: 食評（reviews）模式規劃為 v1.1，目前尚未實作。

***

### 部署

```bash
npm install
npm run build
apify push
```

本地測試：

```bash
apify run --input='{"keywords":["壽司"],"maxItems":5}'
```

***

### 免責聲明

本工具僅用於公開可存取資料的合法研究與分析用途。使用者應自行遵守 [OpenRice 服務條款](https://www.openrice.com/zh/hongkong/legal/terms)，請勿大量爬取、勿用於商業競爭目的、勿儲存個人資料。作者對使用者行為不負任何責任。

***

OpenRice 爬蟲、香港餐廳、餐廳資料、食評、餐廳評分、香港美食數據

# Actor input Schema

## `keywords` (type: `array`):

要搜尋的餐廳名稱或菜式關鍵字。每筆搜尋結果計費 $0.002。

## `bulkInput` (type: `string`):

一行一個關鍵字，自動合併到 keywords。

## `district` (type: `string`):

districtId 篩選（由 metadata API 取得）。例如：1019 = 銅鑼灣、2010 = 旺角、1001 = 上環。留空則不篩選地區。

## `cuisine` (type: `string`):

cuisineId 篩選（由 metadata API 取得）。例如：2009 = 日本菜、1004 = 港式。留空則不篩選菜式。

## `maxItems` (type: `integer`):

每個關鍵字最多抓幾筆結果（1–500，預設 50）。

## `proxyConfiguration` (type: `object`):

選用 Apify Proxy 或自訂 proxy。預設不使用 proxy（直連）。

## Actor input object example

```json
{
  "keywords": [
    "壽司",
    "燒烤",
    "日本料理"
  ],
  "bulkInput": "壽司\n燒烤\n港式",
  "district": "1019",
  "cuisine": "2009",
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keywords": [
        "壽司"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("claude_code_reviewer/openrice-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "keywords": ["壽司"] }

# Run the Actor and wait for it to finish
run = client.actor("claude_code_reviewer/openrice-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keywords": [
    "壽司"
  ]
}' |
apify call claude_code_reviewer/openrice-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=claude_code_reviewer/openrice-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/auya2ehdSn75MC7LW/builds/pUcV0TWQQwvioYeMu/openapi.json
