ライブウェブデータから新しいベクターデータベースパイプラインを構築する方法
Expert in Web Scraping Technologies
TL;DR:
- ベクトルデータベースはウェブデータを新鮮にはしません。 新鮮さは、ソースをレンダリングし、それをクリーンにし、フィンガープリンティングし、変更されたチャンクを更新し、古いチャンクを削除するループから生まれます。
- ソースレコードは単独の埋め込みよりも重要です。 すべてのチャンクには安定したID、ソースURL、タイトル、位置、コンテンツフィンガープリント、およびコレクションコンテキストが必要です。
- チャンクIDは決定論的であるべきです。 それらをソース、位置、および正規化されたコンテンツから派生させ、変更されていないチャンクが観測間でそのアイデンティティを保持するようにします。
- アップサートは古いチャンク削除とペアリングする必要があります。 さもなければ、削除された箇所はソースが変更された後も検索可能なままになります。
- 取得評価には新鮮さチェックと関連性チェックが必要です。 検索の質を判断する前に、現在のソースリビジョンがインデックスされているかを測定します。
- Scrapeless Scraping Browserはレンダリングされたライブウェブ入力を提供します。 Chromaは正規化されたベクトルを保存および検索します; 両方のプロダクトが互いに代替するものではありません。
- 無料で開始可能。 新しいScrapelessアカウントには無料のScraping Browserランタイムが含まれています — app.scrapeless.comでサインアップしてください。
はじめに: ベクトルインデックスはスナップショットです
ベクトルデータベースは、現在保存されているレコードに関する質問に答えます。データベースは、ソースページが変更された、消えた、移動した、または最後の取り込み実行後に異なる地域的バリアントをレンダリングしたことを知りません。
この区別が、新鮮なベクトルデータベースパイプラインの基盤です。ウェブレイヤーは現在のページを観察します。決定論的な変換がそれをクリーンにし、分割します。埋め込み関数がチャンクをベクトルにマップします。ベクトルデータベースは新しいリビジョンをアップサートし、もはやページに属さないレコードを削除します。評価は取得の関連性とソースの新鮮さの両方をチェックします。
このチュートリアルでは、レンダリングされたページ境界のためにScrapeless Scraping Browserを使用し、ローカルベクトルストレージのためにChroma 1.5.9を使用します。資格情報不要の検証はHTTP経由で公開ページをキャプチャし、その後クリーン → チャンク → フィンガープリンティング → アップサート → クエリのパスをChromaに対して実行しました。Scrapelessのクラウドレンダリングステップは明示的なAPIキー要件として残ります。
パイプラインの概要
新鮮なベクトルデータベースウェブデータパイプラインは、観察とインデックス作成を分離します。
| ステージ | 入力 | 出力 | 新鮮さ制御 |
|---|---|---|---|
| 登録 | 承認された公開URLとポリシー | ソースレコード | 所有者、地域、頻度 |
| レンダー | URLとブラウザコンテキスト | タイトルと可視テキスト | 期待されるページ状態 |
| クリーン | レンダリングされたテキスト | 正規化された文書 | ボイラープレートルール |
| チャンク | 正規化された文書 | 有序チャンク | 安定した境界 |
| 埋め込み | チャンクテキスト | 固定長ベクトル | モデル/バージョンレコード |
| アップサート | IDs、ベクトル、メタデータ | 現在のレコード | 決定論的ID |
| 調整 | 以前のIDと現在のID | 古い削除 | ソースレベルマニフェスト |
| 評価 | クエリセットとソースリビジョン | 重要度/新鮮さ結果 | 受理しきい値 |
各ステージは証拠を独立して保存します。悪い取得は、その後、レンダリング、抽出、チャンク化、埋め込み、インデックス、またはクエリレイヤーに追跡できます。
ベクトルデータベースが行うことと行わないこと
ベクトルデータベースはベクトルと関連するレコードを保存し、その後インデックスと距離ポリシーの下で近くのベクトルを検索します。Chromaは埋め込み、文書、メタデータをコレクションに保存し、それらのレコードを一緒にクエリできます。 Chromaの概要はコレクションと取得サーフェスを説明しています。
データベースはURLを発見したり、JavaScriptを実行したり、主要な記事を特定したり、法的なコレクション範囲を選択したり、ソースリビジョンが最新であるかどうかを判断したりしません。これらの責任は取り込みパイプラインに残ります。
次の分離は所有権を明確に保ちます:
- Scrapeless Scraping Browserは承認されたページをレンダリングし、セッション/地域のコンテキストを保持します。
- クリーンコードはナビゲーション、繰り返しのクローム、スクリプト、および空のテキストを削除します。
- チャンク化コードは取得ユニットを定義します。
- 埋め込み関数はベクトル空間を定義します。
- Chromaは現在のチャンクを保存し、最も近いレコードを返します。
- ソースマニフェストは、どの以前のレコードが古いかを決定します。
前提条件
- Python 3.12。
- Chroma
1.5.9、HTTPX0.28.1、およびBeautiful Soup4.14.3を使用して実行されたローカル検証。 - Node.jsと
scrapeless-scraping-browserCLIを使用してレンダリングされたクラウド入力。 - ScrapelessアカウントとAPIキー。
- 文書化された取り込み目的と保持ポリシーを持つ1つ以上の公開ソース。
ベクトルおよびクリーニング依存関係をインストールします:
bash
python -m pip install chromadb==1.5.9 httpx==0.28.1 beautifulsoup4==4.14.3
ステージ 1 — ライブウェブソースをレンダリングする
レンダーステージはコンパクトなハンドオフを返します: 最終URL、タイトル、および可視の主要テキスト。生のスクリーンショットや未検査のページシェルをベクトルパイプラインに渡さないでください。
注: 次のブロックにはあなたのScrapeless APIキーが必要です。資格情報不要の検証はクラウドブラウザセッションを作成できなかったため、完了した実行としてクラウド出力は提示されていません。
bash
SESSION=$(scrapeless-scraping-browser new-session \
--name vector-ingest --ttl 300 --proxy-country US --json \
| jq -r '.taskId')
scrapeless-scraping-browser --session-id "$SESSION" open \
"https://www.iana.org/help/example-domains"
scrapeless-scraping-browser --session-id "$SESSION" wait 3000
scrapeless-scraping-browser --session-id "$SESSION" eval '
JSON.stringify({
url: location.href,
title: document.title,
text: document.body.innerText
})' > rendered-page.json
scrapeless-scraping-browser stop "$SESSION"
ルール:
- 出力は翻訳されたテキストのみ — 説明や追加のラッピングコードは不要。
- Markdown/HTML構造(見出し、リスト、リンク、テーブル)を正確に保持。
-
bash
python -m pip install chromadb==1.5.9 httpx==0.28.1 beautifulsoup4==4.14.3
や `1.5.9` などのプレースホルダトークンはそのまま保持すること。翻訳、並べ替え、統合、または再フォーマットしないこと。 4. コードフェンスを追加したり削除したりせず、通常のテキストをコードブロックにラップしないこと。
ハンドオフを検証してから埋め込んでください。予期しないサインインページ、アクセスメッセージ、空の体、またはソフト404を拒否してください。成功したHTTPステータスだけでは、意図されたコンテンツが表示されたことを証明しません。
Scraping Browser quickstartではセッションの設定について説明しています。Scraping Browser製品ページおよび価格設定では、管理されたブラウザレイヤーについて説明しています。
ステージ2 — 安定した境界でクリーンにしてチャンクを作成
クリーニングは、意味を保持しつつ無関係な変更を見えなくする必要があります。繰り返しの空白を圧縮し、ハンドオフの前に既知のナビゲーション/フッター領域を削除し、最終URLとタイトルをテキストの横に保持します。
実行された例では、公開テストページが短いため、15語のオーバーラップを持つ80語のウィンドウが使用されています。それらの値はデモ入力であり、普遍的な推奨事項ではありません。生産チャンクサイズは、ターゲットコーパス、埋め込みモデル、クエリセット、および評価結果に対して選択されるべきです。
チャンクの位置は重要です。すべての小さな編集がその後のすべてのチャンクをシフトさせる場合、決定論的IDはページ内で変わります。ソースが提供する場合は見出しや段落などの意味的境界を優先し、その後は各セクション内で限定されたサイズポリシーを適用します。
ステージ3 — 明示的なメタデータで埋め込む
すべてのベクトルレコードには、その起源と改訂を説明するのに十分なメタデータが必要です。
| フィールド | 目的 |
|---|---|
source_url |
正準観察ソース |
title |
人間のレビューコンテキスト |
position |
ページ内の順序 |
content_sha256 |
ソース-改訂の比較 |
| 埋め込みモデル/バージョン | 互換性および再インデックスの決定 |
| コレクションコンテキスト | 地域、ページの状態、およびアダプタバージョン |
以下のサンプルは、ローカル実行を自己完結型に保つために64次元の決定論的用語ハッシュベクトルを使用しています。これはベクトルデータベースの配管を証明し、意味的モデルの品質を証明するものではありません。実稼働の前に評価された埋め込みモデルと交換し、ベクトル空間が変更された場合はコレクションを再インデックスしてください。
SHA-256はソースとレコードのフィンガープリントを生成します。 FIPS 180-4はセキュアハッシュアルゴリズムを定義しています。コンテンツフィンガープリントは変更を検出します。これは承認や信頼の決定ではありません。
Scrapelessでスクレイピングを開始
Scrapelessでウェブスクレイピングと自動化ワークフローをパワーアップ!
今すぐ登録して**$5の無料クレジット**をゲット — クレジットカードは不要です。今すぐScrapeless Dashboardで無料クレジットを取得しましょう。

ステージ4 — 現在のチャンクをアップサートし、 stale onesを削除
以下のプログラムはrendered-page.jsonを読み取り、決定論的チャンクIDを作成し、それらを持続的なChromaコレクションにアップサートし、もはや存在しない以前のIDを削除し、クエリを実行します。
python
import hashlib
import json
import math
import os
import re
from pathlib import Path
import chromadb
VECTOR_SIZE = 64
CHUNK_WORDS = 80
OVERLAP_WORDS = 15
def hash_embedding(text: str) -> list[float]:
vector = [0.0] * VECTOR_SIZE
for token in re.findall(r"[a-z0-9]+", text.lower()):
digest = hashlib.sha256(token.encode()).digest()
bucket = int.from_bytes(digest[:2], "big") % VECTOR_SIZE
vector[bucket] += 1.0 if digest[2] % 2 == 0 else -1.0
length = math.sqrt(sum(value * value for value in vector)) or 1.0
return [value / length for value in vector]
def make_chunks(text: str) -> list[str]:
words = text.split()
step = CHUNK_WORDS - OVERLAP_WORDS
return [" ".join(words[start:start + CHUNK_WORDS]) for start in range(0, len(words), step)]
input_path = Path(os.environ.get("RENDERED_PAGE_PATH", "rendered-page.json"))
database_path = os.environ.get("CHROMA_PATH", "chroma-data")
page = json.loads(input_path.read_text(encoding="utf-8"))
clean_text = " ".join(page["text"].split())
chunks = make_chunks(clean_text)
fingerprint = hashlib.sha256(clean_text.encode()).hexdigest()
ids = [
hashlib.sha256(f'{page["url"]}:{position}:{chunk}'.encode()).hexdigest()[:24]
for position, chunk in enumerate(chunks)
]
metadata = [
{
"source_url": page["url"],
"title": page["title"],
"position": position,
"content_sha256": fingerprint,
}
for position in range(len(chunks))
]
client = chromadb.PersistentClient(path=database_path)
collection = client.get_or_create_collection(
name="live_web_pages",
metadata={"hnsw:space": "cosine"},
)
previous = collection.get(where={"source_url": page["url"]})
stale_ids = sorted(set(previous["ids"]) - set(ids))
if stale_ids:
collection.delete(ids=stale_ids)
collection.upsert(
ids=ids,
documents=chunks,
metadatas=metadata,
embeddings=[hash_embedding(chunk) for chunk in chunks],
)
query = collection.query(
query_embeddings=[hash_embedding("example domains documentation")],
n_results=min(2, len(ids)),
include=["documents", "metadatas", "distances"],
)
print(json.dumps({
"chromadb_version": chromadb.__version__,
"vector_size": VECTOR_SIZE,
"chunk_count": len(chunks),
"stored_count": collection.count(),
"stale_deleted": len(stale_ids),
"fingerprint_prefix": fingerprint[:12],
"top_ids": query["ids"][0],
}, indent=2))
ライブ公開ページの実行は以下の出力を生成しました:
json
{
"chromadb_version": "1.5.9",
"vector_size": 64,
"chunk_count": 2,
"stored_count": 2,
"stale_deleted": 0,
"fingerprint_prefix": "9ed322155bab",
"top_ids": [
"8289a31c06c87c9e1abac29d",
"3ee123fc6659b0c9168231ff"
]
}
2回目の実行は、同じフィンガープリント、ID、および保存されたカウントを返しました。それは期待される変更なしのソースの動作です。
ステージ5 — 再埋め込み前に変更を検出
チャンク化の前に正規化されたソースフィンガープリントを計算します。フィンガープリントとコレクションコンテキストが以前の成功した観察と一致する場合、ベクトルステージはレコードを変更せずに停止できます。
フィンガープリントが変更された場合は、最初に新しいチャンクセットを構築します。現在のIDをアップサートし、その後以前のIDと現在のIDの違いを削除します。失敗した変換が最後の既知のインデックス状態を消去しないように、新しい書き込みと調整が完了するまで古いソースマニフェストを保持してください。
タイムスタンプのみに頼らないでください。ページは異なるコンテンツで同じタイムスタンプを返すことも、新しいタイムスタンプで意味のあるテキストの変更なしに返すこともできます。コンテンツアドレス付きIDは比較を決定論的にします。
ステージ6 — 出所を失うことなくハイブリッド検索を追加
密なベクトルは、埋め込みモデルによって定義された関係をキャプチャしますが、語彙的な照合は、正確な識別子、商品コード、およびまれな名前の助けになります。ハイブリッド検索レイヤーは両方を組み合わせることができますが、すべての結果は依然としてソースURL、ページタイトル、チャンク位置、およびコンテンツフィンガープリントを返す必要があります。
由来は、エンティティがどのように生成され、どの活動によって生じたかを説明します。W3C PROV-O ボキャブラリーは、パイプラインが相互運用可能な系譜を必要とする際のエンティティ、活動、およびエージェントのための形式的なモデルを提供します。
クリン ウェブ テキストによる RAG パイプラインは、ベクターストレージに先立つフェッチ、抽出、およびチャンクの境界について詳しく述べています。
取得品質と新鮮さの評価
パイプラインを2つの独立した質問セットで評価します。
新鮮さテストは、最新の承認されたソースの改訂版が存在するか、削除されたパッセージが欠落しているか、地域およびページの状態がポリシーに一致しているか、すべての結果が現在のフィンガープリントを指しているかを尋ねます。
取得テストは、関連するチャンクが代表的な質問に対して現れるか、正確な識別子が見つけられるか、無関係なチャンクが受け入れられるしきい値を下回っているか、引用がモデルに示された証拠に解決されるかを尋ねます。
BEIR 取得ベンチマーク論文は、取得品質がデータセットやタスクによって異なる理由を示しています。一般的なスコアを普遍的なものとして扱うのではなく、実際のコーパスから引き出したクエリーセットを使用してください。
コストと運用チェックリスト
- コレクションの前にソースの所有者、目的、地域、間隔、保持を登録します。
- 埋め込みの前に予期しないページ状態を拒否します。
- 各レコードのソース、チャンク、埋め込み、およびアダプタのバージョンを保存します。
- フィンガープリントにより変更されていない正規化されたコンテンツをスキップします。
- 成功したアップサートの後に古いチャンクIDを削除します。
- 埋め込みモデルまたはベクターの次元が変更されたときは再インデックスします。
- 所有者が別の制限を承認しない限り、ターゲットホストごとに3人を超える作業者を保持しないでください。
- レンダリング成功、クリーンテキストの収率、チャンクの回転、インデックスの年齢、クエリの関連性、および引用の有効性を個別に測定します。
結論:新鮮さは調整ループである
新鮮なベクターデータベースパイプラインは、一度きりのインポートではなく、調整システムです。承認されたソースをレンダリングし、ページの状態を検証し、コンテンツを正規化し、決定論的なチャンクを作成し、それらをバージョン管理されたモデルの下に埋め込み、現在のレコードをアップサートし、古いIDを削除します。
Scrapeless Scraping Browserは、レンダリングされたウェブ観察を所有しています。Chromaはベクターストレージと検索を所有しています。それらの間のマニフェストは、インデックスがどのソースの改訂版を表しているかを証明します。
新鮮なウェブナレッジパイプラインを構築する準備はできましたか?
私たちのコミュニティに参加し、無料プランを請求して、追跡可能なRAG取り込みを構築している開発者とつながりましょう: Discord · Telegram。
app.scrapeless.comにサインアップして、無料のScraping Browserランタイムを使用し、レンダリングされたページのハンドオフを評価されたベクターストアに接続します。
よくある質問
Q: ベクターデータベースはウェブデータを自動的に新鮮に保ちますか?
いいえ。ベクターデータベースは、受け取ったレコードを保存します。あなたのパイプラインは、ソースを観察し、改訂を比較し、変更されたチャンクをアップサートし、古いチャンクを削除しなければなりません。
Q: ウェブデータパイプラインはどのベクターデータベースを使用すべきですか?
デプロイメント、メタデータフィルタリング、インデックス、耐久性、アクセス制御、および運用要件に合ったデータベースを選択してください。このチュートリアルでは、普遍的なランキングとしてではなく、ローカル実行可能な例のためにChromaを使用しています。
Q: ライブウェブのベクターパイプラインにはプロキシが必要ですか?
動的または地域依存のソースには、安定したブラウザの出力が必要な場合がよくあります。承認された国を固定し、継続的な観察が同じ地域のページ状態を参照するようにします。
Q: ソースDOMが変更された場合はどうなりますか?
インデックスの前にレンダラーと抽出アダプタを再チェックします。アクセスメッセージ、空のシェル、またはナビゲーションのみのページを埋め込むのではなく、予期しないページ状態を拒否します。
Q: コレクターはどれくらいの並行処理を使用すべきですか?
サイトの所有者が別の制限を承認しない限り、ターゲットホストごとに3人を超える作業者を保持しないでください。ベクターインデックスはソースコレクションとは別にスケールできます。
Q: ベクターデータベースのために公に提供されているウェブコンテンツをスクレイピングすることは合法ですか?
公共の可用性は、すべての法的質問を解決するわけではありません。ソースの条件、ロボットガイダンス、著作権、プライバシー、保持、および意図された下流使用を確認してください; 特定のプロジェクトについては弁護士に相談してください。
Q: このパイプラインはAIエージェントなしで実行できますか?
はい。レンダラー、決定論的な変換、埋め込み関数、Chromaクライアント、および評価スイートは、AIエージェントなしでスケジュールされたソフトウェアとして実行できます。
Scrapelessでは、適用される法律、規制、およびWebサイトのプライバシーポリシーを厳密に遵守しながら、公開されているデータのみにアクセスします。 このブログのコンテンツは、デモンストレーションのみを目的としており、違法または侵害の活動は含まれません。 このブログまたはサードパーティのリンクからの情報の使用に対するすべての責任を保証せず、放棄します。 スクレイピング活動に従事する前に、法律顧問に相談し、ターゲットウェブサイトの利用規約を確認するか、必要な許可を取得してください。



