フラスコにパイソンウェブスクレーパーを造ること


ウェブサイトは現在、世界中のユーザーが毎日消費される貴重な情報の富を含んでいます.これらの統計は、研究または特別な関心のどんな主題の役に立つ資産でもあります.この情報を収集するときは、ほぼ間違いなく自分で手動でコピーして貼り付け見つける.
それはもちろん、あなたとはうまくいかない.あなたは、Webスクレーピングが入っているこのシンプルな、より自動化されたメソッドが必要です.
だから、正確にWebスクレーピングですか?名前が意味するように、それは単に指定された形式でウェブページの非構造化されたHTML情報の自動抽出であり、それを構造化して、データベースにそれを保存するか、将来の消費のためにCSVファイルとしてそれを保存します.
Pythonライブラリは、今日アクセス可能なWebスクレーピング技術のリストのトップにあります.Beautiful Soup 最も人気のあるPythonウェブは、ライブラリをこすりです.
このチュートリアルでは、美しいスープを使用してウェブスクレーピングを見ていきますRequests . 我々は、ウェブスクラップアプリケーションを構築しますFlask , Pythonの最も軽量なWebフレームワーク.

動作方法
  • アプリケーションを読み込む
  • 取得対象のURLとタグを取得する例
  • 応答-要求された要素(s)の内容を受け取ります.
  • イメージのために、あなたのダウンロードディレクトリにイメージを保存するダウンロード機能が、あります
  • ライブプレビューhere

    1 .プロジェクト設定.
    このプロジェクトのために、私は、バックエンドの機能だけでなく、神社のテンプレートとループに集中します.CSSやHTMLコードの残りの部分については詳しく説明しません.フルプロジェクトコードhere .
    このプロジェクトをローカルマシン上で実行するにはhere .

    Don't worry if you don't understand what's going on behind the scenes now that your project is up and running. Fill your coffee mug, because things are about to get interesting.



    2 .プロジェクトの詳細.
    主な議論ファイルは次のようになります.
  • アプリ.パイ
  • テンプレート/インデックス.HTML

  • アプリ.パイ
    紹介で述べたように、フラスコ、美しいスープ、リクエストライブラリーを利用します.まず第一に、我々はアプリにフラスコと美しいスープからいくつかの機能をインポートします.Pyファイル.
    URLを検証して解析する必要があるので、Python用のURL処理モジュールをインポートします.urllib , 他の組み込みライブラリも同様です.
    from flask import (
        Flask,
        render_template,
        request,
        redirect,
        flash,
        url_for,
        current_app
    )
    import urllib.request 
    from urllib.parse import urlparse,urljoin
    from bs4 import BeautifulSoup
    import requests,validators,json ,uuid,pathlib,os
    
    以下に示すように、フラスコインスタンスを作成しなければなりません.
    app = Flask(__name__)
    
    次に、最初のルートについては、以下のようにHTMLテンプレートを返す関数を構築します.
    @app.route("/",methods=("GET", "POST"), strict_slashes=False)
    def index():
        # Actual parsing codes goes here
        return render_template("index.html")
    
    スクラップを開始するには、ユーザーがポストリクエストを送信したことを確認する必要があります.
    if request.method == "POST":
    
    我々の機能の中で我々は美しいスープを使用して、実際の解析を扱う
    try:
        global requested_url,specific_element,tag
    
        requested_url = request.form.get('urltext')
        tag = request.form.get('specificElement')
    
        source = requests.get(requested_url).text
        soup = BeautifulSoup(source, "html.parser")
        specific_element = soup.find_all(tag)
    
        counter = len(specific_element)
    
        image_paths = image_handler(
            tag,
            specific_element,
            requested_url
            )
    
        return render_template("index.html",
            url = requested_url,
            counter=counter,
            image_paths=image_paths,
            results = specific_element
            )
    
    except Exception as e:
        flash(e, "danger")
    
    以下のスクリプトを説明するために、イメージパスを受け入れて、完全なURLを生成するための関数を書いているので、フォームフィールド入力をグローバルに利用できなければならないので、グローバル変数として定義します.
    global requested_url,specific_element,tag
    
    次のステップは、下記のように、フォームフィールドから2つのグローバル変数に値を設定することです.
     requested_url = request.form.get('urltext')
     tag = request.form.get('specificElement')
    
    次のコード行最初の行はHTTPリクエストをユーザ指定URLに送信します.requested_url . サーバーはウェブページの生のHTML内容を提供することによって要求に答えます..text() と変数に代入するsource .
    source = requests.get(requested_url).text
    
    HTML形式をテキスト形式で抽出した後、ページを解析する必要がありますhtml.parser 構文解析ライブラリとして.これを行うことで、HTMLデータの入れ子/ツリー構造を生成するだけです.
    soup = BeautifulSoup(source, "html.parser")
    
    我々は全体のドキュメントを必要としないので、我々は必要な要素を発見するために木をナビゲートします.ユーザーがフォームフィールドに入力するタグ.
    specific_element = soup.find_all(tag)
    
    また、発見された結果のカウントが必要です.その結果、変数を作成します.counter をカウントします.
    counter = len(specific_element)
    
    我々が見ることができるように、変数image_paths は、image_handler() , ユーザが提供するURL、タグ、および解析されたページから抽出した特定の要素を受け入れる.我々はこの機能をスキップして、それが何かを見るために、後でそれに戻って来ます.
    image_paths = image_handler(
        tag,
        specific_element,
        requested_url
        )
    
    戻り値のステートメントと一緒に構文解析の結果を渡し、HTMLテンプレートで利用可能にします.
    return render_template("index.html",
        url = requested_url,
        counter=counter,
        image_paths=image_paths,
        results = specific_element
        )
    
    ウェブサイトでイメージを参照するとき、開発者はしばしば絶対URLまたは相対的なURLを使用します.絶対URLは扱うのが簡単です、しかし、相対的なルートは若干の処理を必要とします.
    例えば/uploads/image.png , 例えば、彼らが発信する場所を決定するのは難しいでしょう.したがって、我々は我々のイメージ経路を検証するために以前に呼ばれるものと類似した機能をつくります.
    def image_handler(tag,specific_element,requested_url):
        image_paths = []
        if tag == 'img':
            images = [img['src'] for img in specific_element]
            for i in specific_element:
                image_path = i.attrs['src']
                valid_imgpath = validators.url(image_path)
                if valid_imgpath == True:
                    full_path = image_path
                else:
                    full_path = urljoin(requested_url, image_path)
                    image_paths.append(full_path)
    
        return image_paths
    
    この関数は、tag はイメージタグで、イメージのsrc属性値を抽出し、絶対パスであるかどうかを確認します.これがそうでないならば、それは目標のベースURLへの相対パスに加わります.
    https://example.com + /uploads/image.png
    

    これらのピクチャパスはリストに保存され、関数が取り消されたときに返されます.
    テンプレート/インデックス.HTML
    次は何かスクラップ結果をユーザに提供しなければならない.この場合、神社のテンプレートとループを使用します.
    <div class="col-md-8">
        <p><span class="badge bg-success">{{ counter }}</span> Scrap Results for <a
                href="{{ url }}"> {{ url }}</a> </p>
        <div class="bg-white shadow p-4 rounded results">
            {% if results %}
            {% for result in results %}
            <p> {{ result | join(' ') }} </p>
            {% endfor %}
            {% endif %}
            {% for path in image_paths %}
            <a href=" {{  path }} "> <img src=" {{ path }} " class="img"> </a>
            {% endfor %}
        </div>
        {% if image_paths %}
        <a href="{{url_for('downloader')}}" class="btn btn-primary m-2" id="download">Download
            Images<i class="bi bi-cloud-arrow-down-fill m-2"></i></a>
        {% endif %}
    </div>
    
    上記のHTMLコードフラグメントでは、結果として発見されたURLの数を印字します.以下のサンプルを見てください.

    結果カウントとURL
    まず、結果リストがcountとURLの下で使用可能かどうかを確認します.これは、取得されたテキストです.
    ただし、出力を出力すると表示されます| join(' ') 同様に動作する|striptags 変数の結果からすべてのHTMLタグを削除します.
    の代わりに

    そうしましょう

    我々は、写真を囲むためにアンカータグを使用してhref and src プロパティ.
    {% for path in image_paths %}
    <a href=" {{  path }} ">
    <img src=" {{ path }} " class="img">
    </a>
    {% endfor %}
    
    また、画像を検索した場合のみダウンロードオプションを表示します.それで、我々はこれを成し遂げるために文を使用します.下記のコードを見てください.
    {% if image_paths %}
    <a href="{{url_for('downloader')}}" class="btn btn-primary m-2" id="download">
    Download Images
    <i class="bi bi-cloud-arrow-down-fill m-2"></i>
    </a>
    {% endif %}
    
    最後に、少なくとも、我々はあまりにも画像をダウンロードする必要があります.
    @app.route("/download",methods=("GET", "POST"), strict_slashes=False)
    def downloader():
        try:
            for img in image_handler(tag,specific_element,requested_url):
                image_url = img
    
                filename = str(uuid.uuid4())
                file_ext = pathlib.Path(image_url).suffix
    
                picture_filename = filename + file_ext
    
                downloads_path = str(pathlib.Path.home() / "Downloads")
    
                picture_path  = os.path.join(downloads_path, picture_filename
                )
    
    
            flash("Images saved in your Downloads directory", "success")
    
        except Exception as e:
            flash(e, "danger")
    
        return redirect(url_for('index'))
    
    The uuid ライブラリは、ダウンロードしたファイルの一意の名前を生成するために上記のダウンロード機能によって使用されます.
    filename = str(uuid.uuid4())
    
    then pathlib.Path() イメージパスから画像の拡張子を取り除きます.
    file_ext = pathlib.Path(image_url).suffix
    
    つは、拡張子を含むイメージ名を生成するために結合されます.その後、ダウンロードディレクトリパスが埋め込まれます.これにより、画像を保存する場所を指定できます.
    picture_path  = os.path.join(downloads_path, picture_filename)
    
    次のコード行は実際の画像ダウンロードを処理します.
    urllib.request.urlretrieve(image_url, picture_path)
    
    パラメータとしてurllib.request.urlretrieve() ダウンロードするイメージとそれが新しい名前で保存されるディレクトリを受け入れます.その結果、写真は静的ディレクトリ内のダウンロードディレクトリに保存されます.
    最後に、モジュールとしてアプリケーションを実行するためにフラスコに指示します.
        if __name__ == "__main__":
            app.run(debug=True)
    
    これを読んで時間を割いていただき、ありがとうございました.
    以下のセクションで、共有して、コメントを残してください.Twitter上でさらに更新とヒントフラスコと反応の開発に従ってください.