6
6

LangChainのWebBaseLoaderでWebページの内容が取得できない場合の対処法

Posted at

LangChainには、Webページをドキュメントとして取得する「WebBaseLoader」が用意されています。Webページによっては、WebBaseLoaderで内容が取得できません。

WebBaseLoaderでページを取得してみる

例えば、OpenAI社のNewsのページを取得してみます。

ライブラリーをインストールします。

Shell
pip install langchain langchain-community beautifulsoup4

以下のコードを実行します。

app.py
import json
import os

os.environ["USER_AGENT"] = (
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"
)

from langchain_community.document_loaders import WebBaseLoader

loader = WebBaseLoader(
    web_path="https://openai.com/index/introducing-openai-o1-preview/",
)
documents = loader.load()

for document in documents:
    print("--- page_content ---")
    print(document.page_content[0:100])
    print("-" * 20)

    print(json.dumps(document.metadata, indent=2, ensure_ascii=False))
--- page_content ---












Please turn JavaScript on and reload the page.Please enable Cookies and reload the page.
--------------------
{
  "source": "https://openai.com/index/introducing-openai-o1-preview/",
  "language": "No language found."
}

JavaScriptとクッキーを有効にしてねというメッセージしか取得できませんでした。

HTMLソースを取得し確認すると、「noscript」タグの内容だけが取得できており、ブラウザ上に表示されるコンテンツは取得できませんでした。

image.png

このように、WebBaseLoaderではJavaScriptで動的に表示コンテンツを作成しているページはうまく内容を取得できません。

AsyncChromiumLoaderを使う

このような動的なページを取得する際には、「AsyncChromiumLoader」を使うと動作が改善します。
内部でplaywrightを使用しているのでインストールします。

Shell
pip install playwright

playwrightに必要なブラウザモジュールをインストールします。

Shell
playwright install-deps
playwright install chromium

これで準備が整いました。WebBaseLoaderの代わりにAsyncChromiumLoaderを使用します。

app.py
import json

from langchain_community.document_loaders import AsyncChromiumLoader

loader = AsyncChromiumLoader(
    urls=["https://openai.com/index/introducing-openai-o1-preview/"],
    user_agent="Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36",
)
documents = loader.load()


for document in documents:
    print("--- page_content ---")
    print(document.page_content[0:100])
    print("-" * 20)

    print(json.dumps(document.metadata, indent=2, ensure_ascii=False))
--- page_content ---
<!DOCTYPE html><html lang="en-US" dir="ltr" style="--document-width: 1280px; --gutter-size: max(20px
--------------------
{
  "source": "https://openai.com/index/introducing-openai-o1-preview/"
}

WebBaseLoaderでは、HTML内のテキストのみを勝手にパースして取得しますが、AsyncChromiumLoaderはHTML全体が返却されます。

どちらが良いとは言えないですが、WebBaseLoaderと同様の動作にしたい場合は、BeautifulSoupを間に挟むと良いでしょう。

app.py
import json

from bs4 import BeautifulSoup
from langchain_community.document_loaders import AsyncChromiumLoader

loader = AsyncChromiumLoader(
    urls=["https://openai.com/index/introducing-openai-o1-preview/"],
    user_agent="Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36",
)
documents = loader.load()


def get_text(page_content: str):
    soup = BeautifulSoup(page_content, features="html.parser")
    return soup.get_text()


for document in documents:
    print("--- page_content ---")
    print(get_text(document.page_content)[0:100])
    print("-" * 20)

    print(json.dumps(document.metadata, indent=2, ensure_ascii=False))
--- page_content ---
Introducing OpenAI o1 | OpenAISkip to main contentResearchProductsSafetyCompanyIntroducing OpenAI o1
--------------------
{
  "source": "https://openai.com/index/introducing-openai-o1-preview/"
}

いい感じになりました。

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6