python: seleniumをBeautifulSoupに書き直す

プログラミング
スポンサーリンク




こんにちは、おみです。

前回までseleniumを用いてwebスクレイピングを行ってきました。

ですが、HTMLを取得するために必要ないwebページも表示する必要があり、処理がスマートに行えません。

そこで今回は、seleniumで記述している部分をBeautifulSoupに書き直したいと思います。

スポンサーリンク

使用するライブラリの説明

(1) webbrowser

ブラウザを表示するために使用します。

(2) requests

WEBページのHTMLを取得するために使用します。

入っていない場合はインストールします。

pip install requests

(3) BeautifulSoup

HTMLの解析に使用します。

入っていない場合はインストールします。

$ pip install beautifulsoup4

ソースコード

前回と大きく変わった部分は太字で示しています。

↓ファイル構造

 

・Main.py

import tkinter as tk

from src.Model import Model
from src.View import View
from src.Controller import Controller


class Application(tk.Frame):
    def __init__(self, root):
        # スーパークラスのコンストラクタを呼び出し
        super().__init__(root)

        # モデルをインスタンス化
        self.model = Model(root)

        # ビューをインスタンス化
        self.view = View(root, self.model)

        # コントローラーをインスタンス化
        self.controller = Controller(root, self.model, self.view)

        # Viewにメソッドをセット
        self.view.btn_search["command"] = lambda: self.controller.call_btn_clicked()

        # 画面の設定
        root.geometry(str(self.model.width) + "x" + str(self.model.height))
        root.title(self.model.title)


def main():
    root = tk.Tk()
    window = Application(root)
    window.mainloop()


if __name__ == "__main__":
    main()

・Model.py

import configparser as c
import tkinter as tk

# ---------------------------------
# スクレイピング用のモジュールをインポート
# ---------------------------------
# ブラウザ表示用
import urllib.parse
import webbrowser
# HTMLダウンロード用
import requests
# HTML解析用
import bs4


class Model(object):
    def __init__(self, root):
        # ---------------------------------
        # 初期設定
        # ---------------------------------
        # configファイルを読み込み
        self.config = c.ConfigParser()
        self.config.read("config.ini")

        # 画面タイトルを取得
        self.title = self.config["DISPLAY_INFO"]["title"]

        # 画面サイズを取得
        self.width = self.config["DISPLAY_INFO"]["width"]
        self.height = self.config["DISPLAY_INFO"]["height"]

        # 表示ページ数を取得
        self.pages = self.config["SETTING"]["pages"]

        # 画面パーツに入力した値を格納する変数を宣言
        self.ent_search_text = tk.StringVar()

    # ボタンクリック時起動メソッド
    def btn_clicked(self):
        # 検索結果一覧のwebページのHTMLを取得する
        search_result = requests.get("https://www.google.com/search?q={}".format((self.ent_search_text.get()))).content

        # 取得したHTMLを使用してBeautifulSoupオブジェクトを生成する
        result_soup = bs4.BeautifulSoup(search_result, "html.parser")

        # 検索結果のリンクを含むaタグのリストを取得
        a_tags = result_soup.select('div[class="kCrYT"] > a')

        # 指定された件数分検索結果を表示する
        for idx in range(0, min(int(self.pages), len(a_tags))):
            # aタグからurlを取得
            url = a_tags[idx].get('href').split('&sa=U&')[0].replace('/url?q=', '')

            # ブラウザをインスタンス化
            browser = webbrowser.get()

            # urlを指定してwebページを表示
            browser.open(url)

・View.py

import tkinter as tk


class View(object):
    def __init__(self, root, model):
        self.root = root
        self.model = model

        # ---------------------------------
        # 画面の部品を生成
        # ---------------------------------
        # 検索欄ラベル
        self.lbl_search = tk.Label(
            root,
            text="word"
        )

        # 検索欄
        self.ent_search = tk.Entry(
            root,
            textvariable=model.ent_search_text,
            width=30
        )

        # 検索ボタン
        self.btn_search = tk.Button(
            root,
            text="search",
            command=lambda: model.btn_clicked()
        )

        # ---------------------------------
        # 画面の部品を配置
        # ---------------------------------
        self.lbl_search.grid(row=0, column=0)
        self.ent_search.grid(row=0, column=1)
        self.btn_search.grid(row=0, column=2)

・Controller.py

class Controller(object):
    def __init__(self, root, model, view):
        self.root = root
        self.model = model
        self.view = view

    # 検索ボタンクリック時起動メソッドを定義
    def call_btn_clicked(self):
        self.model.btn_clicked()

・config.ini

[DISPLAY_INFO]
title = "検索結果取得"
width = 400
height = 30

[SETTING]
pages = 3

詳細の説明

検索結果の一覧を取得する処理は、次の手順で行なっています。

  1. 検索結果ページのHTMLを使用し、BeautifulSoupオブジェクトを生成する
  2. BeautifulSoupオブジェクトを使用し、aタグの一覧を取得する
  3. aタグからURLを取り出す
  4. URLを新しいウィンドウで開く

 

1では、requestsを使用して検索結果のWEBページのHTMLを取得した後、それを元にBeautifulSoupオブジェクトを生成します。

search_result = requests.get("https://www.google.com/search?q={}".format((self.ent_search_text.get()))).content

result_soup = bs4.BeautifulSoup(search_result, "html.parser")

 

2では、1で取得したHTMLからURLが記載されているaタグのリストを取得しています。

a_tags = result_soup.select('div[class="kCrYT"] > a')

 

3では、aタグからURLを取得します。

URLにはクエリパラメータ等必要ない文字列が含まれているので、それらは除去します。

url = a_tags[idx].get('href').split('&sa=U&')[0].replace('/url?q=', '')

 

4では取得したURLを指定して、webページを開きます。

browser = webbrowser.get()
browser.open(url)

次回

検索結果のwebページのタイトルとURLを、CSVファイルに出力できるようにしたいと思います。

↓次回

https://moimoiblog.com/gui-application/show-search-result/python-application-search-result-get4/?preview_id=161&preview_nonce=c0e82477a0&preview=true

参考文献

webbrowser --- 便利なウェブブラウザコントローラー — Python 3.9.4 ドキュメント
Requests: 人間のためのHTTP — requests-docs-ja 1.0.4 documentation
Beautiful Soup のfind_all( ) と select( ) の使い方の違い - ガンマソフト株式会社
PythonによるWebスクレイピングでは、requests と Beautiful Soup の2つのライブラリが定番です。requestsでHTMLをダウンロードし、Beautiful Soup ...

コメント

タイトルとURLをコピーしました