動静ダブル特典

動的 IP50GB毎に +10GB 無料

静的 IP30日毎に +7日 延長 & 500MB 贈呈

今すぐ購入 >

セキュリティ警告最近、フィッシングサイト(rola-ip.com)が当社の旧公式サイトを装っています。ROLA IP の公式サイトは rola-ip.co のみです(ドメイン末尾が .co であることをご確認ください)。安全のため、他のドメインでは決済しないでください。

Naver画像検索をPythonでスクレイピングする方法:APIで取得してCSVに保存

Daniel Zhao

2026年10月10日 · ガイド · 約9分で読める

Naver画像検索のスクレイピングで画像URLやサムネイルを一覧化したい場合は、公式のImage Search APIを使う方法が適しています。Pythonから検索語を渡すと、タイトル、画像URL、サムネイルURL、画像の幅・高さを取得できます。本記事では、最大1,000件の検索結果をCSVに保存するスクリプトを紹介します。

たとえば、韓国向けのコンテンツ調査で検索語ごとの画像リンクを整理する用途に使えます。取得するのはメタデータであり、画像ファイルそのものはダウンロードしません。カードの並び方やプレビューなど、ユーザーが実際に見る画面を調べたい場合は、ブラウザでの観察を組み合わせます。

Naverの画像検索では何を取得できる?

まず、「seoul skyline」のNaver画像検索結果を開いてみましょう。検索欄の下にある「이미지」が画像タブです。各カードにはサムネイル、タイトル、掲載元のドメインが表示され、カードをクリックすると右側に拡大プレビューと掲載元の情報が開きます。

Naverでseoul skylineを検索した画像一覧
図1:Naver画像検索の結果一覧。

画像カードを選択したときのNaverのプレビューパネル
図2:選択した画像の拡大プレビュー。

APIの結果とブラウザ上のカードは、順序や件数が異なることがあります。データを比較する際は、検索語、実行日時、APIパラメーターをセットで記録しておくと整理しやすくなります。

韓国の情報を調べる場合は、同じテーマを日本語・韓国語・英語で検索して結果を比較できます。たとえば「ソウルの夜景」なら、日本語では「ソウル 夜景」、韓国語では 서울 야경、英語では seoul skyline と入力します。検索語を変えると調査対象も変わるため、複数の言語の結果をまとめる際は、CSVの query 列を残して区別します。

公式APIとブラウザのスクレイピングはどう使い分ける?

画像のリンクを表形式で扱うならAPI、表示内容や操作の挙動を調べるならブラウザ、という使い分けが基本です。

方法 向いている用途 特徴
Image Search API 画像URL、サムネイル、サイズの取得 JSONで取得でき、パラメーターでページ送りを指定できる
PlaywrightやSelenium カードの表示順、プレビュー、スクロール後の表示を調査 描画と遅延読み込みを待ち、実際のDOMを確認する
画像ファイルのダウンロード ピクセルデータを使う処理 検索結果の取得とは別工程。利用条件は掲載元やライセンスに従う

Image Search APIは画像検索用です。地図の座標や商品在庫を取得するAPIとは用途が異なります。

手順1:Naver DevelopersでClient IDとClient Secretを取得する

Naver Developersでアプリケーションを登録し、Search APIを有効にして、Client IDとClient Secretを取得します。これらは後ほど環境変数に設定します。

Naver Image Search APIの公式ドキュメントでは、画像検索のエンドポイントとパラメーターが公開されています。

  • リクエスト方式:GET
  • エンドポイント:https://openapi.naver.com/v1/search/image
  • 認証ヘッダー:X-Naver-Client-Id、X-Naver-Client-Secret

Naver Developersの画像検索APIドキュメント
図3:画像検索APIのドキュメント。

パラメーター 意味 値
query 検索語 必須
display 1回のリクエストで取得する件数 デフォルト10、1~100
start 取得を開始する位置 1~1,000
sort 並び順 sim:類似度順、date:日付順

本記事のコードは sort=sim を使い、1回の実行で最大1,000件を要求します。この上限はスクリプトの仕様であり、各検索語に必ず1,000件の結果があるという意味ではありません。

APIのフィールドとCSV列の対応

APIフィールド CSV列 内容
入力した検索語 query どの検索語で取得したか
title title 画像が見つかった文書のタイトル
link image_url 画像URL
thumbnail thumbnail_url サムネイルURL
sizewidth width 画像の幅(ピクセル)
sizeheight height 画像の高さ(ピクセル)

title は写真の正式名称とは限りません。サイズのフィールドはドキュメント上では文字列として定義されているため、CSVには受け取った値をそのまま保存します。

Naver Image Search APIのレスポンスフィールド一覧
図4:レスポンスの各フィールド。

手順2:Python環境と認証情報を準備する

仮想環境を作り、HTTPリクエスト用の requests をインストールします。YOUR_CLIENT_ID と YOUR_CLIENT_SECRET は取得した値に置き換えてください。

macOS・Linux

python3 -m venv .venv
source .venv/bin/activate
python -m pip install "requests==2.34.2"
export NAVER_CLIENT_ID='YOUR_CLIENT_ID'
export NAVER_CLIENT_SECRET='YOUR_CLIENT_SECRET'

Windows PowerShell

仮想環境のPythonを直接指定すると、環境の有効化操作を省けます。

py -m venv .venv
.\.venv\Scripts\python.exe -m pip install "requests==2.34.2"
$env:NAVER_CLIENT_ID = 'YOUR_CLIENT_ID'
$env:NAVER_CLIENT_SECRET = 'YOUR_CLIENT_SECRET'

環境変数は現在のターミナルで有効です。同じターミナルからスクリプトを実行してください。

手順3:Pythonで画像検索結果をCSVに保存する

次のコードを naver_image_api.py として保存します。APIキーは環境変数から読み込み、検索語と取得上限はコマンドライン引数で指定します。

コードは各レスポンスのHTTPステータスを確認し、リクエストが失敗した場合は原因を表示して終了します。取得途中でエラーになった場合は、その実行分のCSVを書き込みません。APIエラー時に自動再試行は行わず、エラー内容を確認してから再実行する方式です。

タイトルのHTMLタグを除去し、CSVは utf-8-sig で保存します。日本語・韓国語をExcelで扱う際にも使いやすい形式です。

"""Export Naver Image Search API metadata to CSV. Requires API credentials."""
import argparse
import csv
import os
import re
from html import unescape

import requests

API_URL = "https://openapi.naver.com/v1/search/image"
FIELDNAMES = ["query", "title", "image_url", "thumbnail_url", "width", "height"]


def clean_title(value):
    return unescape(re.sub(r"<[^>]+>", "", value or ""))


def fetch_images(query, limit, client_id, client_secret, session=None):
    if not 1 <= limit <= 1000:
        raise ValueError("limitは1~1000の範囲で指定してください")
    http = session or requests.Session()
    headers = {
        "X-Naver-Client-Id": client_id,
        "X-Naver-Client-Secret": client_secret,
    }
    rows = []
    for start in range(1, limit + 1, 100):
        display = min(100, limit - len(rows))
        response = http.get(
            API_URL,
            headers=headers,
            params={"query": query, "display": display, "start": start, "sort": "sim"},
            timeout=20,
        )
        response.raise_for_status()
        payload = response.json()

        items = payload.get("items", [])
        for item in items:
            rows.append({
                "query": query,
                "title": clean_title(item.get("title")),
                "image_url": item.get("link", ""),
                "thumbnail_url": item.get("thumbnail", ""),
                "width": item.get("sizewidth", ""),
                "height": item.get("sizeheight", ""),
            })
        if len(items) < display:
            break

    return rows


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("query", help="検索語。例:seoul skyline")
    parser.add_argument("--limit", type=int, default=100)
    parser.add_argument("--output", default="naver_images.csv")
    args = parser.parse_args()
    client_id = os.environ.get("NAVER_CLIENT_ID")
    client_secret = os.environ.get("NAVER_CLIENT_SECRET")
    if not client_id or not client_secret:
        parser.error("先にNAVER_CLIENT_IDとNAVER_CLIENT_SECRETを設定してください")
    if not args.query.strip():
        parser.error("queryは空欄にできません")
    if not 1 <= args.limit <= 1000:
        parser.error("limitは1~1000の範囲で指定してください")
    try:
        rows = fetch_images(args.query, args.limit, client_id, client_secret)
    except requests.HTTPError as exc:
        response = exc.response
        status = response.status_code if response is not None else None
        advice = {
            400: "query、display、start、sortの値を確認してください。",
            401: "Client IDとClient Secretを確認してください。",
            403: "アプリケーションの権限とSearch APIの有効化を確認してください。",
            429: "利用枠とリクエスト頻度を確認し、再試行前にリクエスト間隔を調整してください。",
        }.get(status, "APIのステータスとドキュメントを確認してから再試行してください。")
        if status == 429 and response is not None:
            retry_after = response.headers.get("Retry-After")
            if retry_after:
                advice += f" Retry-After: {retry_after}."
        parser.exit(1, f"APIリクエストに失敗しました(HTTP {status}):{advice}\nこの実行ではCSVを保存していません。\n")
    except requests.Timeout:
        parser.exit(1, "リクエストがタイムアウトしました。接続を確認して再試行してください。CSVは保存していません。\n")
    except requests.RequestException:
        parser.exit(1, "リクエストまたはレスポンスの処理に失敗しました。接続とAPIレスポンスの形式を確認してください。CSVは保存していません。\n")
    with open(args.output, "w", encoding="utf-8-sig", newline="") as file:
        writer = csv.DictWriter(file, fieldnames=FIELDNAMES)
        writer.writeheader()
        writer.writerows(rows)
    print(f"{len(rows)}行を{args.output}に保存しました")


if __name__ == "__main__":
    main()

スクリプトを実行する

macOS・Linuxでは、仮想環境を有効にした状態で実行します。

python naver_image_api.py '서울 야경' --limit 120 --output naver_images.csv

Windows PowerShellでは、仮想環境のPythonを指定します。

.\.venv\Scripts\python.exe naver_image_api.py '서울 야경' --limit 120 --output naver_images.csv

成功すると、N行をnaver_images.csvに保存しました という形式で保存件数とファイル名が表示されます。N はその実行で取得できた件数です。認証情報が未設定の場合は、環境変数を設定するよう案内して終了します。

ページネーションの動き

--limit 250 を指定した場合、リクエストは最大3回です。

リクエスト start display
1回目 1 100
2回目 101 100
3回目 201 50

APIが指定件数より少ない結果を返した時点で取得を終了します。たとえば2回目に30件しか返らなければ、3回目は実行しません。

重複した画像URLはどう扱う?

このコードはAPIが返したレコードをそのまま保存するため、同じ画像URLが複数行に現れる場合があります。--limit は取得レコード数の上限です。

画像URLごとに1行へまとめたい場合は、出力後に image_url 列で重複を整理します。複数の検索語を横断して分析する場合は、同じ画像がどの検索語で見つかったかも残しておくと役立ちます。

手順4:CSVをExcelで開いて内容を確認する

CSVのヘッダーは次の6列です。

query,title,image_url,thumbnail_url,width,height

数行を確認し、検索語、読みやすいタイトル、画像・サムネイルのURL、幅と高さが保存されているかを見ます。件数が --limit より少ない場合は、その実行の items 数と検索語を確認してください。

Excelで文字化けする場合は、[データ]→[テキストまたはCSVから]で読み込み、文字コードをUTF-8に指定します。utf-8-sig は文字コードの認識を助けますが、Excelのバージョンや読み込み方法に応じて設定を確認すると確実です。

PlaywrightやSeleniumを使うべきケース

ブラウザで表示されるカードやクリック後のプレビューを調べる場合は、PlaywrightやSeleniumでページを開きます。APIの取得処理とは分けて、次の順序で記録します。

  1. 検索語と「이미지」タブを確認する。
  2. 最初のカードが表示されるまで待つ。
  3. スクロール後、新しいカード数が安定するまで待つ。
  4. タイトル、サムネイル、掲載元を記録し、URLで重複を整理する。
  5. 検索語、アクセス日時、画面のスクリーンショットを保存する。

セレクターは実際のDOMで確認します。画像の遅延読み込みがあるため、短時間に連続してスクロールすると記録漏れが起こりやすくなります。ページ構造が変わった場合は、開発者ツールで要素と通信内容を確認してセレクターを更新してください。

地域別のNaver画像検索を調べるときのRola IPの使い方

Rola IPは、ブラウザの接続地域を切り替えて画像検索の表示を比較する場面で使えます。具体的な用途はNaverの地域別検索QAガイドで確認できます。公式APIは直接接続から始めましょう。プロキシはAPIの認証情報や利用枠を置き換えるものではありません。

接続先ホスト、ポート、ユーザー名、パスワードはRola IPのクイックスタートに沿って設定します。ローテーション型レジデンシャルプロキシの設定では、国・州・都市の指定方法を確認できます。

Naverの地域別検索調査に使うRola IPのプロキシ

同じ比較セッションではセッションIDをそろえ、調査時間に合わせて sessiontime を設定します。プロキシの設定パラメーターによると、指定範囲は1~120分です。たとえば sessiontime-10 は10分を指定し、その間は同じIPの維持を試みます。独立した比較には別のセッションIDを使います。-f-1 はリクエストごとにIPを切り替えるため、接続地域を固定して観察する用途とは使い分けます。

地域比較では、検索語、指定地域、実際の出口IPと所在地、日時、ブラウザ、言語設定、ログイン状態、アクセスURLを記録します。言語やログイン状態も結果に影響するため、接続地域以外の条件はそろえてください。ブラウザのプロキシ設定は、別途実行するPythonの requests には自動適用されません。

よくあるエラーと対処方法

現象 確認する項目 対処
認証情報が未設定と表示される 現在のターミナルの環境変数 NAVER_CLIENT_ID と NAVER_CLIENT_SECRET を設定する
HTTP 401 Client ID・Client Secret アプリケーションの認証情報と設定値を照合する
HTTP 403 Search APIの有効化と権限 Naver Developersのアプリケーション設定を確認する
HTTP 400 query、display、start、sort 値と公式の指定範囲を照合する
HTTP 429 レスポンスのエラー内容、利用枠、リクエスト頻度 Retry-After があれば従い、頻度を下げる。利用枠を使い切った場合はリセットを待つか追加利用を確認する
CSVの件数が少ない 検索語とAPIの items 数 取得上限と実際の返却件数を区別する
画像URLを開けない 掲載元のURL変更やアクセス条件 掲載元を確認し、リンクの状態を記録する

APIのエラーはNaverの共通エラーコード一覧も参照してください。エラー発生後は原因を確認して再実行します。

まとめ

Naver画像検索のメタデータを表にまとめるなら、公式APIとPythonを組み合わせると、画像URL、サムネイル、サイズをCSVへ整理できます。カードやプレビューの観察はブラウザで行い、地域差を比較する場合は接続地域とブラウザの条件を記録します。目的に合わせてAPIとブラウザを使い分けることが、扱いやすいデータを集めるポイントです。

よくある質問