SECTION 14

スクレイピングと
リスト自動構築

Webからのデータ収集を自動化 — 営業リストもAIが作る

LCREATOR.Inc Google AI 研修プログラム

SECTION 14

スクレイピングとは

OVERVIEW

Webページからデータを自動取得する技術

スクレイピング(Scraping)とは、Webサイトの情報をプログラムで自動的に収集・抽出する技術です。 ブラウザで見ているページの「裏側」にあるHTML構造を解析し、必要なデータだけを取り出します。

身近な例: Googleの検索エンジンも、世界中のWebページをスクレイピング(クロール)して検索結果を構築しています。
Webページ(HTML)
スクレイピングプログラム
構造化データ(スプレッドシート等)

SECTION 14

なぜスクレイピングが必要なのか?

WHY

手動データ収集の限界

手動の場合

  • 1件あたり2〜3分のコピペ作業
  • 100件で3〜5時間、ミスも発生
  • データが古くなるたびに再作業
  • 担当者が休むと止まる

自動化の場合

  • 1,000件を数分で収集
  • 入力ミス・表記揺れゼロ
  • 定期実行で常に最新データ
  • 人手不要で24時間稼働

自動化のメリット4軸

timer

速度

数千件のデータを数分で収集

正確性

コピペミスが発生しない

sync

再現性

同じ処理を何度でも繰り返せる

trending_up

拡張性

他ツールとの連携で価値が倍増

SECTION 14

GASでWebデータ取得: UrlFetchApp

CODE

Google Apps ScriptのUrlFetchAppを使えば、 任意のURLからHTMLを取得できます。

GAS function fetchWebPage() { // URLを指定してHTMLを取得 const url = 'https://example.com/list'; const response = UrlFetchApp.fetch(url); const html = response.getContentText(); // レスポンスコードを確認 const code = response.getResponseCode(); Logger.log('Status: ' + code); // HTMLの長さを確認 Logger.log('HTML Length: ' + html.length); }

UrlFetchApp の主要メソッド

メソッド説明
.fetch(url)GETリクエストを送信
.fetch(url, options)POST等のカスタムリクエスト
.getContentText()レスポンスボディを文字列で取得
.getResponseCode()HTTPステータスコード取得
.getHeaders()レスポンスヘッダー取得
warning
GASのUrlFetchAppにはアクセス制限があります。1日あたりの実行回数に上限があるため、大量取得時は注意してください。

SECTION 14

HTMLの構造理解: DOM・タグ・クラス

BASICS

スクレイピングでデータを正確に抽出するには、HTMLの構造を理解することが必要です。

HTML <div class="company-card"> <h3 class="name">株式会社ABC</h3> <p class="address">東京都渋谷区...</p> <span class="tel">03-1234-5678</span> </div>
lightbulb
ブラウザの「開発者ツール」(F12キー)でHTMLの構造をリアルタイムに確認できます。

基本用語

用語説明
タグHTMLの要素を囲む記号<h3>, <div>
クラス要素のカテゴリ名class="name"
ID要素の一意な識別子id="main"
DOMHTMLのツリー構造親→子の階層
属性タグに付加する情報href="..."
スキル需要の円グラフ / 給与分布ヒストグラム

SECTION 14

正規表現でデータ抽出

REGEX

GASではXMLパーサーが使えないため、正規表現(RegExp)を使ってHTMLからデータを抽出します。

GAS function extractEmails(html) { // メールアドレスを抽出 const pattern = /[\w.+-]+@[\w-]+\.[\w.]+/g; const matches = html.match(pattern); return matches || []; } function extractPhones(html) { // 電話番号を抽出(03-1234-5678形式) const pattern = /\d{2,4}-\d{2,4}-\d{4}/g; const matches = html.match(pattern); return matches || []; }

よく使う正規表現パターン

目的パターン
メールアドレス[\w.+-]+@[\w-]+\.[\w.]+
電話番号\d{2,4}-\d{2,4}-\d{4}
URLリンクhttps?://[\w/:%#\$&\?\(\)~\.=\+\-]+
タグ内テキスト<h3[^>]*>(.+?)</h3>
class指定要素class="name">(.+?)<
GAS // タグ内のテキストを抽出する汎用関数 function extractByClass(html, cls) { const re = new RegExp( 'class="' + cls + '"[^>]*>([^<]+)', 'g' ); const results = []; let m; while (m = re.exec(html)) { results.push(m[1].trim()); } return results; }

SECTION 14

IMPORTXML / IMPORTHTML: ノーコードスクレイピング

NO-CODE

スプレッドシートの組み込み関数

コードを書かなくても、スプレッドシートの関数だけでWebデータを取得できます。

Spreadsheet // Webページからテーブルを取得 =IMPORTHTML( "https://example.com/ranking", "table", 1 ) // XPathで特定のデータを取得 =IMPORTXML( "https://example.com/company", "//h2[@class='name']" ) // RSSフィードを取得 =IMPORTFEED( "https://example.com/rss" )

関数の比較

関数取得対象難易度
IMPORTHTML table要素 / リスト要素(ul, ol) 簡単
IMPORTXML XPathで指定した要素 中級
IMPORTFEED RSS / Atomフィード 簡単
IMPORTDATA CSV / TSVファイル 簡単
warning
IMPORT系関数はGoogleのサーバーからアクセスするため、ログインが必要なページやIP制限のあるサイトでは使えません。
check_circle
おすすめ: まずIMPORT関数で試し、取得できない場合にGASへステップアップしましょう。

実践パターン

ビジネスで活用するスクレイピング 4つのユースケース

SECTION 14

パターン1: 企業情報リスト構築

PATTERN 1

Webサイトから企業データを抽出

業界ポータルや企業検索サイトから、社名・住所・電話番号・URLなどを一括取得し、 営業リストを自動構築します。

GAS function buildCompanyList() { const sheet = SpreadsheetApp .getActiveSheet(); const baseUrl = 'https://example.com/list?page='; for (let page = 1; page <= 10; page++) { const html = UrlFetchApp .fetch(baseUrl + page) .getContentText(); // 社名・住所・電話番号を抽出 const names = extractByClass(html, 'company-name'); const addrs = extractByClass(html, 'address'); const tels = extractPhones(html); // スプレッドシートに書き出し names.forEach((name, i) => { sheet.appendRow([name, addrs[i], tels[i]]); }); // アクセス間隔を空ける(マナー) Utilities.sleep(2000); } }

出力イメージ

社名住所電話番号
株式会社ABC東京都渋谷区...03-1234-5678
DEF株式会社大阪府北区...06-9876-5432
GHI合同会社福岡県博多区...092-111-2222

手動で3日かかるリスト作成が、スクリプトなら10分で完了。しかもミスなし。

lightbulb
Utilities.sleep(2000) で2秒待機。サーバーに負荷をかけないマナーです。

SECTION 14

パターン2: 価格比較リスト

PATTERN 2

ECサイトから商品価格を定期取得

競合他社の価格をスクレイピングで収集し、自社の価格戦略に活かします。 GASのトリガー機能で毎日自動実行も可能です。

GAS function trackPrices() { const urls = [ 'https://shop-a.com/product/123', 'https://shop-b.com/item/456', ]; const sheet = SpreadsheetApp .getActiveSheet(); const today = new Date(); urls.forEach(url => { const html = UrlFetchApp.fetch(url) .getContentText(); const price = html.match( /class="price"[^>]*>([\d,]+)/ ); if (price) { sheet.appendRow([today, url, price[1]]); } Utilities.sleep(2000); }); }

価格推移の可視化

価格推移グラフ(スプレッドシートのグラフ機能)
ポイント: GASのトリガーで毎朝8時に自動実行すれば、価格変動を自動で追跡できます。 スプレッドシートのグラフ機能と組み合わせて可視化しましょう。
lightbulb
ECサイトによっては利用規約でスクレイピングを禁止している場合があります。必ず事前に確認してください。

SECTION 14

パターン3: ニュース収集 + AI要約

PATTERN 3

RSSフィード + Gemini APIで業界ニュースダイジェスト

RSSフィードからニュース記事を自動収集し、Gemini APIで要約。 毎朝のSlack投稿やメール送信まで自動化できます。

RSSフィード
GAS取得
Gemini要約
Slack通知
GAS function newsDigest() { const feedUrl = 'https://news.example.com/rss'; const xml = UrlFetchApp .fetch(feedUrl).getContentText(); const doc = XmlService.parse(xml); // 記事タイトルと概要を抽出 const items = doc .getRootElement() .getChildren('channel')[0] .getChildren('item'); let summary = ''; items.slice(0, 5).forEach(item => { summary += item .getChildText('title') + '\n'; }); // Gemini APIで要約 const digest = summarizeWithGemini( summary ); }

SECTION 14

パターン4: 求人情報収集と分析

PATTERN 4

求人サイトからのデータ取得

求人情報を定期的にスクレイピングし、業界の給与水準、必要スキル、募集傾向を分析します。 採用戦略や自社の給与テーブル見直しに活用できます。

取得するデータ項目

項目活用方法
職種名トレンド分析
給与範囲市場相場の把握
必要スキル研修計画への反映
勤務地エリア別の需要分析
企業規模競合の採用動向

分析ダッシュボードのイメージ

850
収集求人数
¥520万
平均年収
スキル需要の円グラフ / 給与分布ヒストグラム
block
求人サイトの多くはスクレイピングを利用規約で禁止しています。API提供があればそちらを優先してください。

SECTION 14

AIによるデータ整形: 生データをGeminiで構造化

AI + DATA

スクレイピング + AI の組み合わせ

スクレイピングで取得した「生のテキストデータ」は、そのままでは使いにくいことがあります。 Gemini APIを使って、自然言語を構造化データに変換します。

GAS function structureWithGemini(rawText) { const apiKey = ScriptApp.getOAuthToken(); const prompt = `以下のテキストから 企業情報をJSON形式で抽出してください: - company_name(社名) - address(住所) - phone(電話番号) - industry(業種) テキスト: ${rawText}`; const payload = { contents: [{ parts: [{ text: prompt }] }] }; const res = UrlFetchApp.fetch( `https://us-central1-aiplatform.googleapis .com/v1beta/models/gemini-2.5-flash :generateContent`, { method: 'post', contentType: 'application/json', headers: { 'Authorization': `Bearer ${token}` }, payload: JSON.stringify(payload) } ); return JSON.parse( res.getContentText() ); }

Before / After

Before: 生テキスト

株式会社テックイノベーション
〒150-0001 東京都渋谷区神宮前1-2-3
TEL: 03-1234-5678 / IT・ソフトウェア

After: 構造化JSON

{ "company_name": "株式会社テックイノベーション", "address": "東京都渋谷区神宮前1-2-3", "phone": "03-1234-5678", "industry": "IT・ソフトウェア" }
活用シーン: 名刺情報、会社概要ページ、プレスリリースなど、フォーマットが統一されていないデータの正規化に最適です。

法的・倫理的配慮

スクレイピングを安全に使うために知るべきルール

SECTION 14

法的注意事項: 守るべき4つのルール

LEGAL

1. robots.txt

Webサイトが「クロールしてよい範囲」を定義するファイル。 https://example.com/robots.txt で確認可能。 Disallow に指定されたパスはアクセスしない。

2. 利用規約(Terms of Service)

多くのWebサイトは利用規約でスクレイピングを制限・禁止しています。 特にSNS、ECサイトは明示的に禁止していることが多い。 違反は民事訴訟のリスク

3. 著作権法

著作権法30条の4: 情報解析目的であれば著作物の利用は原則OK。 ただし、他者の利益を不当に害する場合は違法となる可能性あり。 データベースの著作物には特別な保護がある点にも注意。

4. 不正アクセス禁止法

ログインが必要なページを、認証をバイパスしてアクセスすると 不正アクセス禁止法に抵触する可能性。 公開ページのみを対象にするのが鉄則。

warning
必須チェック: スクレイピングを始める前に、(1) robots.txtの確認 (2) 利用規約の確認 (3) 法務部門への相談 — この3ステップを必ず実行してください。

SECTION 14

エシカルスクレイピング: 技術的マナー

ETHICS

守るべき5つのルール

  • アクセス間隔を空ける: 最低1〜2秒のsleepを入れる。連続アクセスはDDoS攻撃と見なされるリスクあり。
  • User-Agentを設定: ボット名と連絡先を明記し、透明性を確保する。
  • robots.txtを尊重: Disallowされたパスにはアクセスしない。
  • 最小限のデータ収集: 必要なデータだけを取得し、全ページの丸ごとコピーは避ける。
  • キャッシュを活用: 同じページへの再アクセスを減らし、サーバー負荷を軽減する。

User-Agent設定の例

GAS const options = { headers: { 'User-Agent': 'MyCompanyBot/1.0 (contact@example.com)' }, muteHttpExceptions: true }; const response = UrlFetchApp.fetch( url, options );
NG例:
  • 1秒間に100回以上のアクセス
  • ログイン済みセッションの無断利用
  • 取得データの無断再配布・転売
  • 個人情報の大量収集

ハンズオン

実際に手を動かしてスクレイピングを体験しよう

SECTION 14

ハンズオン1: IMPORTXML関数を使う

HANDS-ON 1
1

新しいスプレッドシートを作成

Google Driveで「新しいスプレッドシート」を作成します。名前を「スクレイピング練習」にしましょう。

2

セルA1に IMPORTHTML を入力

以下の関数でWikipediaの表を取得します:

=IMPORTHTML( "https://ja.wikipedia.org/wiki/都道府県", "table", 1 )
3

セルD1に IMPORTXML を入力

XPathで特定の要素だけを取得します:

=IMPORTXML( "https://example.com", "//h1" )
4

結果を確認

数秒待つとデータが自動的に展開されます。エラーが出た場合はURLやXPathを確認しましょう。

IMPORTHTML関数でWikipediaの表を取得した画面
check_circle
完了基準: スプレッドシートにWebページのテーブルデータが表示されればOKです。

SECTION 14

ハンズオン2: GASでWebデータ取得

HANDS-ON 2
1

Apps Scriptエディタを開く

スプレッドシートの「拡張機能」→「Apps Script」を開きます。

2

以下のコードを貼り付け

function scrapeExample() { const url = 'https://example.com'; const html = UrlFetchApp.fetch(url) .getContentText(); // タイトルタグの中身を抽出 const title = html.match( /<title>(.+?)<\/title>/ ); const sheet = SpreadsheetApp .getActiveSheet(); sheet.getRange('A1') .setValue(title ? title[1] : '取得失敗'); sheet.getRange('B1') .setValue(html.length + ' 文字'); }
3

実行して結果を確認

「実行」ボタンを押し、初回は権限を承認。スプレッドシートに結果が書き込まれます。

Apps Scriptエディタでコードを実行する画面
チャレンジ: URLを変更して、別のWebサイトのタイトルも取得してみましょう。 例: ニュースサイトやブログなど。

SECTION 14

ハンズオン3: 取得データをAIで整形

HANDS-ON 3
1

Gemini APIキーを設定

Apps Script → プロジェクトの設定 → スクリプトプロパティにGCP_PROJECT_IDを追加

2

生データをGeminiに送信

function cleanWithAI() { const rawData = SpreadsheetApp .getActiveSheet() .getRange('A1:A10') .getValues().flat().join('\n'); const result = structureWithGemini( rawData ); Logger.log(result); }
3

構造化データをシートに書き戻す

JSON形式で返ってきたデータを各カラムに展開してスプレッドシートに保存します。

1. 生データ(バラバラなテキスト)
2. Gemini APIで構造化を指示
3. JSON → スプレッドシートに展開
check_circle
完了基準: 生テキストが「社名」「住所」「電話番号」の列に分割されて表示されればOKです。

SECTION 14

トラブルシューティング

DEBUG
エラー / 症状 原因 対策
403 Forbidden サーバーがアクセスを拒否。User-Agent未設定やIP制限 User-Agentヘッダーを設定する。robots.txtを確認する
429 Too Many Requests 短時間に大量のリクエストを送信した Utilities.sleep() でアクセス間隔を広げる(3〜5秒推奨)
HTMLが空 / 文字化け JavaScriptで動的に生成されるページ GASのUrlFetchAppではJS実行不可。APIやIMPORT関数を検討
正規表現で取得できない HTMLの構造が想定と異なる 開発者ツールで実際のHTML構造を確認する
IMPORTXML #N/A XPathが正しくない、またはサイトがアクセスを拒否 XPathを開発者ツールのCopyXPathで取得し直す
GAS実行時間超過 6分の実行制限に到達 処理を分割し、トリガーで複数回に分けて実行する
lightbulb
デバッグのコツ: Logger.log() で中間データを出力し、どのステップで問題が起きているかを特定しましょう。「実行ログ」(Ctrl+Enter)で確認できます。

SECTION 14

スクレイピング全体パイプライン

PIPELINE

ETL(Extract → Transform → Load)のフレームワークで整理します。

Extract
データ抽出
Transform
AI整形
Load
保存・共有
Automate
定期実行

Extract

  • UrlFetchApp
  • IMPORTXML
  • IMPORTHTML
  • 正規表現

Transform

  • Gemini API
  • 正規化・重複除去
  • スコアリング
  • カテゴリ分類

Load

  • スプレッドシート
  • CSV出力
  • Firestore
  • BigQuery

Automate

  • GASトリガー
  • 毎日/毎週実行
  • Slack通知
  • メール送信

SECTION 14

GASトリガーで定期実行を自動化

AUTOMATION

完全自動化への最後のピース

GASのトリガー機能を使えば、スクレイピング処理を毎日・毎週・毎月、指定した時刻に自動実行できます。 人手をかけずにリストを常に最新に保てます。

GAS // トリガーをコードで設定する方法 function createDailyTrigger() { ScriptApp.newTrigger('buildCompanyList') .timeBased() .everyDays(1) .atHour(7) .create(); } // 毎週月曜日に実行 function createWeeklyTrigger() { ScriptApp.newTrigger('newsDigest') .timeBased() .onWeekDay(ScriptApp.WeekDay.MONDAY) .atHour(8) .create(); }

トリガーの種類

トリガー用途
時間ベース(毎日)営業リスト更新、ニュース収集
時間ベース(毎週)価格比較レポート
スプレッドシート編集時URL追加時に自動スクレイピング
フォーム送信時依頼ベースのデータ収集
GASトリガー設定画面(エディタ → トリガー)
lightbulb
GUIでの設定: Apps Scriptエディタ左サイドバーの時計アイコン →「トリガーを追加」からも設定可能です。

SECTION 14

実践例: 営業リスト自動構築システム

CASE STUDY

全自動パイプラインの構成

Step 1: データ収集(毎朝7:00自動実行)

業界ポータルサイトから新着企業情報をUrlFetchAppで取得

Step 2: AI分析(収集直後に実行)

Gemini APIで企業の業種分類、従業員規模推定、関連度スコアリング

Step 3: リスト保存(自動)

スプレッドシートに追記、重複チェック済みのクリーンデータ

Step 4: 通知(8:00に配信)

新規追加企業をSlack/メールで営業チームに通知

導入効果(想定)

95%
作業時間削減
3x
リスト網羅性
0
入力ミス
24h
稼働時間

人間は「データを集める」作業から解放され、「データを活用する」戦略立案に集中できる。

SECTION 14

セキュリティとベストプラクティス

SECURITY

APIキーの安全な管理

GAS // NG: コードにAPIキーを直接書く const apiKey = 'AIza...'; // 危険! // OK: スクリプトプロパティに保存 const apiKey = ScriptApp.getOAuthToken();

スクリプトプロパティの設定手順

  1. Apps Scriptエディタを開く
  2. 左サイドバー → 歯車アイコン(プロジェクトの設定)
  3. 「スクリプトプロパティ」セクション
  4. 「プロパティを追加」をクリック
  5. プロパティ名: GCP_PROJECT_ID
  6. 値: あなたのAPIキー

チェックリスト

  • APIキーはスクリプトプロパティに保存している
  • エラーハンドリング(try-catch)を実装している
  • アクセス間隔(sleep)を設定している
  • robots.txtを確認した
  • 利用規約を確認した
  • 個人情報を含むデータは取得していない
  • 取得データの保存期間を決めている
warning
スクリプトを社内共有する際、APIキーがコード内に含まれていないか必ず確認してください。

SECTION 14

まとめ

SUMMARY

Extract

UrlFetchApp / IMPORTXML / 正規表現でWebからデータを自動取得

Transform

Gemini APIで生データを構造化・分類・スコアリング

Load & Automate

スプレッドシート保存 + トリガー自動実行で完全自動化

スクレイピングは「データ収集の自動化」。AI整形と組み合わせることで、手動では不可能な規模と速度でビジネスデータを構築できる。ただし、法的・倫理的な配慮を忘れずに。

今日学んだこと:
  • UrlFetchApp / IMPORTXML / 正規表現の使い方
  • 4つの実践パターン(企業/価格/ニュース/求人)
  • 法的注意事項とエシカルスクレイピング
  • Gemini APIによるデータ構造化
次回の準備:
  • Google Cloudコンソールにログインできることを確認
  • Vertex AIの概要ページを事前に閲覧
  • curlコマンドの基本的な使い方を予習

セクション14 完了

お疲れさまでした!次のセクションに進みましょう。

次へ → セクション15: Vertex AI 基礎と API設計
学習項目
7
ハンズオン
3
所要時間
60分
🏠 研修ポータル ▶ この章の動画 📺 動画一覧