Skip to content

PythonでPlaywrightを使用したHTMLのWebスクレイピング。本チュートリアルでは、HTML構造、要素のターゲティング、ページネーション、そして実例を用いたCSVエクスポートを解説します。

Notifications You must be signed in to change notification settings

bright-jp/html-scraping-with-python

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 

Repository files navigation

PythonでのHTML Webスクレイピング

Bright Data Promo

このチュートリアルでは、HTMLの基礎と、Pythonを使用してWebデータを収集・解析・処理する方法を扱います。

包括的なPython Webスクレイピングのリソースが必要ですか? 詳細ガイドはこちらをご覧ください

Introduction to HTML Structure

スクレイピングに入る前に、HTMLの構成要素を理解しておくことが重要です。

HTMLは、Webページの構造とコンポーネントを定義するタグで構成されています。たとえば、<h1> Text </h1> は見出しテキストを定義し、<a href=""> link </a> はハイパーリンクを作成します。

HTML属性は、要素に関する追加情報を提供します。たとえば、<a> </a> タグの href 属性は、リンク先のURLを指定します。

クラスとID は、ページ要素を正確に識別するための重要な属性です。クラスは似た要素をグループ化し、CSSによる一貫したスタイリングや、JavaScriptによる操作に使われます。クラスは .class-name を使って参照します。

W3Schoolsでは、クラスのグルーピングは次のように表示されます。

<div class="city">
  <h2>London</h2>
  <p>London is the capital of England.</p>
</div>

<div class="city">
  <h2>Paris</h2>
  <p>Paris is the capital of France.</p>
</div>

<div class="city">
  <h2>Tokyo</h2>
  <p>Tokyo is the capital of Japan.</p>
</div>

各タイトルと都市セクションが、同じ city クラスを共有する div に囲まれていることに注目してください。

一方で、IDは個々の要素に対して一意でなければなりません(2つの要素が同じIDを共有することはできません)。たとえば、次のH1要素は、それぞれ個別のスタイリング/操作のために固有のIDを持っています。

<h1 id="header1">Hello World!</h1>

<h1 id="header2">Lorem Ipsum Dolor</h1>

ID要素をターゲットにする構文は #id-name です。

Setting Up Your Python Environment

このガイドでは、HTMLスクレイピング用ライブラリが豊富で、初心者にも扱いやすい構文を持つPythonを使用します。Pythonがインストールされているか確認するには、PowerShell(Windows)またはTerminal(macOS)で次のコマンドを実行してください。

python3

Pythonがインストールされている場合はバージョン番号が表示され、そうでない場合はエラーメッセージが表示されます。必要に応じて、Pythonをダウンロードしてインストールしてください。

次に、WebScraper という名前のフォルダを作成し、その中に scraper.py というファイルを作成します。このファイルを、お好みの統合開発環境(IDE)で開いてください。このガイドでは Visual Studio Code を使用します。

VSCode showing the project

IDEは、開発者がコードを書いたり、デバッグしたり、テストプログラムを実行したり、自動化を作成したりするなど、さまざまなことを可能にする包括的なツールです。これを使ってHTMLスクレイパーを開発します。

次に、仮想環境を作成して、グローバルのPythonインストールをスクレイピングプロジェクトから分離します。これにより依存関係の競合を防ぎ、プロジェクトを整理できます。

次のコマンドで virtualenv ライブラリをインストールします。

pip3 install virtualenv

プロジェクトフォルダへ移動します。

cd WebScraper

仮想環境を作成します。

python<version> -m venv <virtual-environment-name>

これにより、プロジェクトフォルダ内に、すべてのパッケージとスクリプト用のディレクトリが作成されます。

Virtual environment folder creation

次に、システムに応じたコマンドで仮想環境を有効化します。

source <virtual-environment-name>/bin/activate #In MacOS and Linux

<virtual-environment-name>/Scripts/activate.bat #In CMD

<virtual-environment-name>/Scripts/Activate.ps1 #In Powershell

有効化に成功すると、ターミナルの左側に仮想環境名が表示されます。

Virtual environment activation indicator

仮想環境を有効化したら、Webスクレイピング用ライブラリをインストールします。選択肢には PlaywrightSeleniumBeautiful SoupScrapy などがあります。このチュートリアルでは、使いやすく、複数ブラウザをサポートし、動的コンテンツを扱え、ヘッドレスモード(GUIなしでのスクレイピング)も提供するため、Playwright を使用します。

pip install pytest-playwright を実行してPlaywrightをインストールし、続けて playwright install で必要なブラウザをインストールしてください。

これでWebスクレイピングを開始する準備が整いました。

Extracting Complete HTML from a Webpage

スクレイピングプロジェクトの最初のステップは、対象Webサイトを選定することです。このチュートリアルでは、このeコマースのテストサイト を使用します。

次に、抽出したい情報を特定します。最初は、ページ全体のHTMLコンテンツを取得します。

スクレイピング対象を特定したら、スクレイパーのコーディングを開始します。Pythonでは、まず必要なPlaywrightライブラリをインポートします。Playwrightには2種類のAPI(syncとasync)があります。今回は非同期コードを書かないため、syncライブラリをインポートします。

from playwright.sync_api import sync_playwright

syncライブラリをインポートしたら、Python関数を定義します。

def main():
    #Rest of the code will be inside this function

Webスクレイピングのコードはすべて、この関数内に記述します。

通常、Webサイトの情報にアクセスするには、ブラウザを開いてタブを作成し、サイトへアクセスします。スクレイピングでは、Playwrightを使ってこれらの操作をコードに置き換えます。ドキュメントによると、インポートした sync_api を呼び出してブラウザを起動できます。

with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)

headless=False を設定すると、実行中にブラウザの内容を確認できます。

ブラウザを起動したら、新しいタブを開き、対象URLへ移動します。

page = browser.new_page()
try:
  page.goto("https://webscraper.io/test-sites/e-commerce/static")
except:
  print("Error")

Note:

これらの行は、前のブラウザ起動コードの下に追加してください。これらのコードはすべて、単一ファイルのmain関数内に含めます。

このコードは、より良いエラーハンドリングのために goto() 関数を try-exceptブロック で囲んでいます。

URLを入力した際にサイトの読み込みを待つのと同様に、コードにも待機時間を追加します。

page.wait_for_timeout(7000) #millisecond value in brackets

Note:

これらの行は、前のコードの下に追加してください。

最後に、ページから完全なHTMLコンテンツを抽出します。

print(page.content())

完全なHTML抽出コードは次のとおりです。

from playwright.sync_api import sync_playwright

def main():
  with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)   
        page = browser.new_page()
        try:
            page.goto("https://webscraper.io/test-sites/e-commerce/static")
        except:
            print("Error")

        page.wait_for_timeout(7000)
        print(page.content())

main()

Visual Studio Codeでは、抽出されたHTMLが次のように表示されます。

Extracted HTML in VSCode

Targeting Specific HTML Elements

Webページ全体を抽出することは可能ですが、特定の情報にフォーカスしたときにWebスクレイピングは本当に価値を発揮します。このセクションでは、サイトの最初のページからノートパソコンのタイトルだけを抽出します。

Laptop titles to extract

特定要素を抽出するには、まずWebサイトの構造を理解します。ページ上で右クリックし、Inspect を選択してください。

Using inspect on the target website

または、次のキーボードショートカットを使用できます。

  • macOS: Cmd + Option + I
  • Windows: Control + Shift + C

対象ページの構造は次のとおりです。

HTML structure of target website

Inspect ウィンドウ左上の選択ツールを使うと、特定のページ要素を確認できます。

Inspecting specific elements

Inspect ウィンドウでノートパソコンのタイトルの1つを選択します。

Inspecting a laptop title

各タイトルが <a> </a> タグに含まれ、それが h4 タグでラップされ、リンクに title クラスが付与されていることが分かります。したがって、title クラスを持つ <h4> タグ内の <a href> タグを探す必要があります。

ターゲットを絞ったスクレイピングプログラムを作成するには、必要なライブラリをインポートし、Python関数を作成し、ブラウザを起動してノートパソコンページへ移動します。

from playwright.sync_api import sync_playwright

def main():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        page = browser.new_page()
        try:
            page.goto("https://webscraper.io/test-sites/e-commerce/static/computers/laptops")

        except:
            print("Error")

        page.wait_for_timeout(7000)

page.goto() 関数内のURLを、ノートパソコン一覧ページへ直接向けるために更新している点に注意してください。

次に、構造分析に基づいて対象要素を特定します。Playwrightは、さまざまな属性を使用して要素を見つけるための locators を提供します。

  • get_by_label() は関連付けられたラベルで要素を見つけます
  • get_by_text() は特定テキストを含む要素を見つけます
  • get_by_alt_text() はaltテキストで画像を見つけます
  • get_by_test_id() はtest IDで要素を見つけます

要素の特定方法については、公式ドキュメントをご確認ください。

すべてのノートパソコンのタイトルを抽出するには、それらを含む <h4> タグを特定します。get_by_role() locatorを使うと、要素の機能(ボタン、チェックボックス、見出しなど)で要素を見つけられます。

titles = page.get_by_role("heading").all()

結果をコンソールに出力します。

print(titles)

出力は要素の配列として表示されます。

Array of heading elements

この出力ではタイトルそのものは表示されず、条件に一致する要素への参照が示されます。title クラスを持つ <a> タグを見つけてテキストを抽出するには、これらの要素をループする必要があります。

CSS locator を使用してパスとクラスで要素を見つけ、all_inner_texts() 関数でテキストを抽出します。

for title in titles:
  laptop = title.locator("a.title").all_inner_texts()

このコードを実行すると、次のような出力が得られます。

Output of title extraction

空の配列を除外するには、次を追加します。

if len(laptop) == 1:
  print(laptop[0])

この特定要素スクレイパーの完全なコードは次のとおりです。

from playwright.sync_api import sync_playwright

def main():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        page = browser.new_page()
        try:
            page.goto("https://webscraper.io/test-sites/e-commerce/static/computers/laptops")

        except:
            print("Error")

        page.wait_for_timeout(7000)

        titles = page.get_by_role("heading").all()

        for title in titles:
            laptop = title.locator("a.title").all_inner_texts()
            if len(laptop) == 1:
                print(laptop[0])

main()

Interacting with Page Elements

複数ページからタイトルを抽出できるように、スクレイパーを強化しましょう。最初のノートパソコンページからタイトルをスクレイピングし、2ページ目へ移動して、そこからもタイトルを抽出します。

タイトル抽出の方法はすでに分かっているので、次ページへの移動方法を学ぶだけです。

このWebサイトには、下部にページネーションボタンがあります。プログラムで「2」ボタンを特定してクリックする必要があります。ページをInspectすると、この要素はテキスト「2」を持つリストアイテム(<li> タグ)であることが分かります。

Pagination element with text "2"

get_by_role() セレクタでリストアイテムを見つけ、get_by_text() セレクタで「2」を含むテキストを見つけられます。

page.get_by_role("listitem").get_by_text("2", exact=True)

これは両方の条件に一致する要素(リストアイテムであり、テキストが正確に「2」)を見つけます。

exact=True パラメータは、完全一致でマッチさせることを保証します。

このボタンをクリックするには、コードを次のように変更します。

page.get_by_role("listitem").get_by_text("2", exact=True).click()

click() 関数は、マッチした要素をクリックします。

次に、ページの読み込みを待ってから、再度タイトルを抽出します。

page.wait_for_timeout(5000)

titles = page.get_by_role("heading").all()

for title in titles:
    laptop = title.locator("a.title").all_inner_texts()
    if len(laptop) == 1:
        print(laptop[0])

複数ページ対応のスクレイパーの完全なコードは次のようになります。

from playwright.sync_api import sync_playwright

def main():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        page = browser.new_page()
        try:
            page.goto("https://webscraper.io/test-sites/e-commerce/static/computers/laptops")

        except:
            print("Error")

        page.wait_for_timeout(7000)

        titles = page.get_by_role("heading").all()

        for title in titles:
            laptop = title.locator("a.title").all_inner_texts()
            if len(laptop) == 1:
                print(laptop[0])
        
        page.get_by_role("listitem").get_by_text("2", exact=True).click()

        page.wait_for_timeout(5000)

        titles = page.get_by_role("heading").all()

        for title in titles:
            laptop = title.locator("a.title").all_inner_texts()
            if len(laptop) == 1:
                print(laptop[0])

main()

Saving Extracted Data to CSV

スクレイピングしたデータは、保存して分析して初めて有用になります。ここでは、ユーザーにスクレイピングするノートパソコンページ数を尋ね、タイトルを抽出してCSVファイルに保存する、より高度なプログラムを作成します。

まず、CSVライブラリをインポートします。

import csv

次に、ユーザー入力に基づいて複数ページを訪問する方法を決めます。

WebサイトのURL構造を見ると、各ノートパソコンページがURLパラメータを使用していることが分かります。たとえば、2ページ目のURLは https://webscraper.io/test-sites/e-commerce/static/computers/laptops?page=2 です。

?page=2 パラメータを変更することで、別のページへ移動できます。ユーザーにスクレイピングするページ数を尋ねます。

pages = int(input("enter the number of pages to scrape: "))

1からユーザー指定の数まで各ページを訪問するには、for ループを使用します。

for i in range(1, pages+1):

range 関数は最初の値(1)から開始し、2番目の値(pages+1)の直前までで終了します。たとえば、range(1,5) は1から4までループします。

次に、ループ変数 i をURLパラメータとして使用して、各ページへアクセスします。Python f-string を使うと、文字列に変数を挿入できます。

f-stringは引用符の前に f を付け、波括弧を使って変数を挿入します。

print(f"The value of the variable is {variable_name_goes_here}")

このスクレイパーでは、ナビゲーションコードにf-stringを使います。

try:
    page.goto(f"https://webscraper.io/test-sites/e-commerce/static/computers/laptops?page={i}")
except:
    print("Error")

ページの読み込みを待って、タイトルを抽出します。

page.wait_for_timeout(7000)
titles = page.get_by_role("heading").all()

次に、CSVファイルを開き、各タイトルをループしてテキストを抽出し、ファイルに書き込みます。

CSVファイルは次で開きます。

with open("laptops.csv", "a") as csvfile:

laptops.csv を追記モード(a)で開いています。追記を使うと、既存データを消さずに新しいデータを追加できます。ファイルが存在しない場合は作成されます。CSVはいくつかのファイルモードをサポートしています。

  • r: デフォルトモード、読み取り専用でファイルを開く
  • w: 書き込み用にファイルを開き、既存データを上書きする
  • a: 追記用にファイルを開き、既存データを保持する
  • r+: 読み取りと書き込みの両方でファイルを開く
  • x: 新しいファイルを作成する

次に、CSVファイルを操作するための writer object を作成します。

writer = csv.writer(csvfile)

各タイトル要素をループし、テキストを抽出します。

for title in titles:
    laptop = title.locator("a.title").all_inner_texts()

空の配列を除外し、有効なタイトルをCSVに書き込むには次のようにします。

if len(laptop) == 1:
    writer.writerow([laptop[0]])

writerow 関数は、CSVファイルに新しい行を追加します。

CSVエクスポート対応スクレイパーの完全なコードは次のとおりです。

from playwright.sync_api import sync_playwright
import csv

def main():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        page = browser.new_page()
        pages = int(input("enter the number of pages to scrape: "))

        for i in range(1, pages+1):
            try:
                page.goto(f"https://webscraper.io/test-sites/e-commerce/static/computers/laptops?page={i}")

            except:
                print("Error")

            page.wait_for_timeout(7000)

            titles = page.get_by_role("heading").all()

            with open("laptops.csv", "a") as csvfile:
                writer = csv.writer(csvfile)
                for title in titles:
                    laptop = title.locator("a.title").all_inner_texts()
                    if len(laptop) == 1:
                        writer.writerow([laptop[0]])

        browser.close()             


main()

このコードを実行すると、CSVファイルは次のようになります。

CSV file output example

Final Thoughts

このガイドでは基本的なWebスクレイピングを示しましたが、実際のユースケースでは、CAPTCHA、レート制限、サイトレイアウトの変更、規制要件などの課題に直面することがよくあります。Bright Dataは、これらの課題に対応するソリューションを提供しており、スクレイピング性能を向上させるための高度なレジデンシャルプロキシ、スケーラブルなスクレイパーを構築するためのWeb Scraper IDE、ブロックされたサイトにアクセスするためのWeb Unblockerなどがあります。

今すぐ無料トライアルを開始しましょう!

About

PythonでPlaywrightを使用したHTMLのWebスクレイピング。本チュートリアルでは、HTML構造、要素のターゲティング、ページネーション、そして実例を用いたCSVエクスポートを解説します。

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published