Python Webスクレイピング

Python学習【365日チャレンジ!】343日目のマスターU(@Udemy11)です。

近くの川の河口でヒラメが釣れているという情報をキャッチしたので、気合を入れて早朝から釣りに行ってきました。

現場に到着すると、結構人が等間隔で釣っていたのですが、かなり広い場所なので、ランガンしながらルアーを投げ続けました。

日が上がって、11時くらいまで投げ倒したのですが、残念ながら、アタリの一つもありませんでした。

私が見える範囲では釣れている人もいなかったので、情報がデマだったのか、広大な範囲なので、ピンポイントで釣れている場所があるのかのどちらかだったのかもしれません。

最近釣りにも行ってなかったので、いい運動にはなりました。

それでは今日も、Python学習を始めましょう。

昨日の復習

昨日は、検索キーワードを入力して、入力されたキーワードで検索した結果のページからURLとタイトルを抽出してみました。

コードはいたって簡単で、search_queryinput()に変更するだけでした。

あまりにも簡単だったので、以前から気になっていたタイトルが文字化けを起こす問題を解決するためにいろいろ調べてみたところ、なんとか解決することができました。

詳細についてはこちらの記事をごらんください。

今日は、Tkinterを使って、入力ウインドウを表示して、テキスト入力窓に入れたキーワードでGoogle検索した結果ページからURLとタイトルを抜き出してCSVに保存するプログラムを作りたいと思います。

インターフェイス

作成する入力ウインドウはこんな感じ

Google検索からURLとタイトルを取得する

それではTkinterを使って入力ウインドウを作成していきましょう。

Tkinterについては、以前学習したこのあたりの記事が参考になるかと思います。

getut_data.py

入力ウインドウの設定は、ファイル名をgetut_data.pyにしてコードを書いていきます。

import tkinter as tk
import scrape_t_u

class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master.geometry()
        self.master.title('Get URL and TITLE')

        self.entry = tk.Entry(self.master,width=40)

        self.menu_bar = tk.Menu(self.master)
        self.master.config(menu=self.menu_bar)

        self.create_widgets()

    def clear_all(self):
        self.entry.delete(0, tk.END)

    def search(self):
        keywords = self.entry.get()
        scrape_t_u.main(keywords)

    def create_widgets(self):
        file_menu = tk.Menu(self.menu_bar)
        file_menu.add_command(label='Exit', command=self.master.quit)
        self.menu_bar.add_cascade(label='File', menu=file_menu)
        self.entry.grid(row=1, column=1, columnspan=6, pady=10, padx=10)
        self.entry.focus_set()

        tk.Button(self.master, text='Clear', width=4,
                  command=lambda: self.clear_all()).grid(row=2, column=5)

        tk.Button(self.master, text='抽出', width=4,
                  command=self.search).grid(row=2, column=6, pady=10)

root = tk.Tk()
app = Application(master=root)
app.mainloop()

コードが長いので、パーツに分けて見ていきましょう。

インポートするライブラリ

import tkinter as tk
import scrape_t_u

インポートするライブラリは、tkinterで、scrape_t_uは、これまでに作成したgoogle検索の結果ページからURLとタイトルをCSVに書き出すファイル(モジュール)です。

フレームの作成

class Application(tk.Frame):

続いて、tk.Frameを継承したApplicationクラスを作成します。

次にクラス内で設定する初期化や関数のコードを定義しています。

初期化

最初は、オブジェクトを生成したときの初期化(__init__です。

    def __init__(self, master=None):
        super().__init__(master)
        self.master.geometry()
        self.master.title('Get URL and TITLE')

        self.entry = tk.Entry(self.master, width=40)

        self.menu_bar = tk.Menu(self.master)
        self.master.config(menu=self.menu_bar)

        self.create_widgets()

コードの最後に記述していますが、Applicationオブジェクトを生成するときに引き渡す引数のmasterのデフォルト値をNoneにして、super().__init__(master)でオーバーライドしていますが、このコードはtkinterのテンプレートのようなものです。

7行目のself.master.geometry()は、作成するボタンや入力枠の配置を細かく指定するためのものです。

8行目は、入力ウインドウのタイトルをGet URL and TITLEに指定しています。

10行目は、入力枠の幅を指定してself.entryとして作成しています。

12行目と13行目では、メニューバーに表示するためのself.menu_barを生成して、self.master.configに指定しています。

15行目で、後で解説する入力ウインドウを設定する関数のcreate_widgets()を実行します。

必要な関数

続いて、入力ウインドウに配置する入力枠の入力を消去するボタンと、Google検索からURLとタイトルをCSVに書き出すモジュールを実行するボタンの関数を定義します。

    def clear_all(self):
        self.entry.delete(0, tk.END)

    def search(self):
        keywords = self.entry.get()
        scrape_t_u.main(keywords)

17行目のclear_allはその名のとおり、18行目で入力枠に入力された文字を消去します。

delete(0, tk.END)は、入力枠の最初の文字から最後の文字までを消去するコードですね。

20行目のsearch()は、21行目のself.entry.get()で入力枠に入力された値を取得して、keywordsに代入して、インポートしたモジュール(scrape_t_u.pymain()の引数にkeywordsを代入して実行するコードです。

ウィジットのレイアウトと動作

    def create_widgets(self):
        file_menu = tk.Menu(self.menu_bar)
        file_menu.add_command(label='Exit', command=self.master.quit)
        self.menu_bar.add_cascade(label='File', menu=file_menu)
        self.entry.grid(row=1, column=1, columnspan=6, pady=10, padx=10)
        self.entry.focus_set()

        tk.Button(self.master, text='Clear', width=4,
                  command=self.clear_all).grid(row=2, column=5)

        tk.Button(self.master, text='抽出', width=4,
                  command=self.search).grid(row=2, column=6, pady=10)

create_widgets()は、ウィジット(入力ウインドウ)のレイアウトとボタン等の実行コマンドの設定です。

25行目で、初期化で設定したmenu_barを使ってfile_menuを作ります。

次に26行目で、そのメニューにExitと表示され、クリックでアプリを終了するコマンドを指定します。

27行目で、file_menuのラベルをFileと表示させています。

28行目で入力枠の表示位置を指定して、29行目で入力ウインドウを表示した際に入力枠に入力できるようにしています。

30行目・31行目で、入力枠に入力した文字を消去するボタンを作成していますが、表示する文字がClearで、実行するコマンドは、先程定義した関数clear_allを指定し、gridで位置を決めています。

33行目・34行目はClearボタンと同じように、抽出したURLとタイトルをCSVに書き出すボタンを作成しています。

表示される文字は抽出で、実行コマンドには関数searchを指定して、gridで位置を決めています。

ファイルの実行

root = tk.Tk()
app = Application(master=root)
app.mainloop()

最後は、クラスからインスタンスを生成してmainloop()でアプリを終了するまでプログラムを待機させる状態にします。

mainloop()はこちらの記事がわかりやすく解説されていますので、参考にどうぞ

コードに戻りますが、37行目でトップレベルのウィジットであるTkをインスタンス化したrootを作り、38行目でApplicationの引数masterrootを入れてappインスタンスを生成したあと、mainloop()でアプリを立ち上げています。

これで、Tkinterで作るインターフェイスは完成で、目標にしていた次の入力ウインドウにコマンドを紐付けたウィジットが完成します。

Google検索からURLとタイトルを取得する

次に、抽出ボタンをクリックしたときに実行するモジュールであるscrape_u_t.pyをチェックしましょうと行きたいところですが、少し長くなってしまったので、明日に持ち越したいと思います。

まとめ

入力ウインドウを作るにあたって、Tkinterのレクチャーで学習した計算機のコードをかなり参考にしました。

必要なコード、不必要なコードを精査しながら今回のコードを書きましたが、たくさんコードを書いて経験を積むことの重要性がひしひしと感じられました。

ほんと書けば書くほど、何がどうなっているのかわかってくるのですが、これは経験してみないことにはわかりません。

例えば、エクセルで計算式を入れているのに、計算結果が表示されないときは、設定オプションで自動計算がオフになっている可能性が考えられますが、何度も経験しているからわかることで、エクセルを使い慣れていない人はなかなか原因を突き止めることができません。

Pythonも同じように、たくさんのコードを書いて経験しておけば、エラーが起こっている原因がわかったり、トラブルに対応できるようになるので、Pythonマスターになるには、コードをたくさん書いて経験を積むしかありません。

Webスクレイピングは、これまでもやりたいと思っていたことなので、コードを書くのが楽しいので、いろいろと試しながら、どんどんコードを書いていきたいとおもいます。

それでは、明日もGood Python!