python: webスクレイピングで検索結果のうち上位数件を表示する

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




こんにちは、おみです。

前回は、テキストボックスに入力した内容を検索し結果を表示する機能を実装しました。

しかし、結果を表示するだけではその後リンクをクリックしてページを表示する作業は残ってしまい、あまりアプリケーションを使う意味がありません。

そこで今回は、検索結果のうち上位数件を自動で表示できるように機能を修正します。

スポンサーリンク

機能の説明

検索欄に知りたい内容を入力し、searchボタンを押すと

検索結果のうち上位数件を別ウィンドウで表示します。

ソースコード

自動表示を行っている部分は太字になっています。

↓ファイル構造

・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
from selenium import webdriver


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):
        # webdriverのインスタンスを生成
        browser = webdriver.Chrome()

        # 検索結果取得用のブラウザを開く
        browser.get("https://www.google.com/search?q={}".format((self.ent_search_text.get())))

        # リンクエレメントのリストを取得
        elems_link_list = browser.find_elements_by_class_name("rc")

        # 指定された件数分検索結果を表示する
        for idx in range(0, min(int(self.pages), len(elems_link_list))):
            # aタグを取得
            a_tag = elems_link_list[idx].find_element_by_tag_name("a")

            # aタグ内のリンクを取得
            url = a_tag.get_attribute("href")

            # 新しいウィンドウを生成
            link_page = webdriver.Chrome()

            # リンクを開く
            link_page.get(url)

        # 検索結果取得用のブラウザを閉じる
        browser.close()

・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. 検索結果からリンクの一覧を取得する
  2. リンクからaタグを取り出す
  3. aタグからURLを取り出す
  4. URLを新しいウィンドウで開く

1では、検索結果のエレメントを取得します。

取得方法はいろいろありますが今回はクラス名: “rc” を指定して取得します。

elems_link_list = browser.find_elements_by_class_name("rc")

↓エレメント取得時の注意点

find_element_***  ... 一致したエレメントのうち最初の一つを取得する。
find_elements_*** ... 一致したエレメント全てを取得する <<< 一覧を取得するので、今回はこちら

2では、検索結果のエレメントからaタグを取得します。

a_tag = elems_link_list[idx].find_element_by_tag_name("a")

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

aタグ内で、URLは”href”という項目に記載されているので、

[aタグエレメント].get_attribute(“href”)

で取り出します。

url = a_tag.get_attribute("href")

↓参考… aタグの例

<a href="https://example.html" target="_blank">ExamplePage</a>

4.では、別のウィンドウを生成してwebページを開きます。

# 新しいウィンドウを生成
link_page = webdriver.Chrome()

# リンクを開く
link_page.get(url)

問題点

seleniumを使用しているため、webページの内容を取得するためにまずページを開かなければなりません。(表示しないようにする方法もあるらしい)

そのため、内容の取得は行いたいが開く必要のないページ(今回であれば検索結果を取得するためのページ)もいちいち開いて処理を行わないといけません。

参考文献

selenium+pythonを使ってテキストのリンクURLを取得する - Qiita
取得したいテキストのリンクはこんな感じだとする。 <p id="id_hoge"><a href="" target="_blank">hoogehoge</a...

 

コメント

  1. […] […]

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