Javaプログラマが退屈なことをPythonにやらせようとした③

.NET、Javaで10年ほど開発の仕事をした後に、
企業と従業員の成長をもっと大切にする会社を増やしたい!と会社を飛び出した者です。

本を頭から進めてきてますが、10章のデバッグは飛ばしました。

今日はWEBスクレイピングです。
VBAでは何度かやってますが、Javaではやったことないので比較して感想は言えないですね。
使用するモジュールごとに簡単にまとめていきます。

今回からサードパーティ製のモジュールも使っていきますよ。

サードパーティ製モジュールダウンロード
コマンドプロンプトでpip使っていきます。次のコマンド打てばOK

webbrowser

標準モジュールなんで、pip使わずとも使えます。

標準ブラウザを起動して、指定URLを表示させるくらいしかできない?
URLが存在するとか、描画完了を待たないのでいくつかのページを自動的に開きたい場合は使えそうです。

ブラウザが表示サポートしているファイルパス(PDFファイルなど)を渡すとブラウザで開いてくれます。

Requests

ここからサードパーティ製モジュールです。
初めて使う場合はインストール必須。

httpリクエストを受け付けていないドメインにget投げたりすると、
get関数の部分で例外発生するので、処理内容によってはここで例外処理も必要ですね。

サンプルコードでは変数resに結果が格納されているので、それを使って後処理します。

htmlソースは全てres.textに格納。
google chromeでページのソースを表示した時と同じ内容が入ってきてるので、単体で使う場合はファイルダウンロードが良いの?

Beautiful Soup

サードパーティ製モジュールです。

webbrowserとrequestsはページを要求する側ですが、
これはその結果(htmlソース)を解析するモジュール。

ページ(htmlソース)の中に特定の要素があるか?とか
要素の中のデータ収集していきます。
これも単体で使う事は少なそうですね。

bs4.BeautifulSoupにhtmlファイルか、htmlソース(requestsのresponse.text)を渡せばBeautifulSoupオブジェクトができるので、
CSSセレクタなどで、要素取り出して各値にアクセスしていきます。

Google検索結果のリンクを収集

これはVBAで作ってみたのをPythonのRequestsとBeautifulSoupに置き換えです。

コマンド引数でも、後入力でも検索ワードを受け取り、
Google検索をリクエストする。

リクエスト結果をBeautifulSoupオブジェクトへ変換して、
検索結果のリンク要素を取り出す。

リンクタイトルとリンクURLを取り出して表示
(ブラウザのページを開く)

anchorのhrefを取得だけだと、冒頭に”/url?q=”というゴミが入り、更に途中にも別のパラメータが入ったので、
replaceとsplitでちょっと強引にリンク先URLだけにしてます。

日本語を含むURLで挙動がおかしい

検索結果のURLに日本語が含まれていない場合は、上記でOKでした。
が、URLに日本語を含むサイトをwebbrowserでopenさせようとしたら、
無効な文字を含むんでいます。と・・・

例えばWikipediaのページでブラウザで表示するとURL表示がこうなるページ。
「https://ja.wikipedia.org/wiki/あいうえお」

収集したURLがこうなってました
「https://ja.wikipedia.org/wiki/%25E3%2581%2582%25E3%2581%2584%25E3%2581%2586%25E3%2581%2588%25E3%2581%258A」
なんか長すぎない?

2回エンコードされている?

対応として、収集したURLのエンコードされた文字列をデコードして、
openするURLした所正しいページを開くようになりました。

どうやら、URLの中の日本語部分が2回エンコードされている様子。
「あいうえお」
↓URLエンコード
「%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A」
↓更にURLエンコード
「%25E3%2581%2582%25E3%2581%2584%25E3%2581%2586%25E3%2581%2588%25E3%2581%258A」
収集したURLと一致しました!

webbrowser.open()ではURLを1回デコードしているけど、
よくわからない文字列になってしまうので正しいページが表示されなくなっていました。

URLにエンコードされた部分があった場合は、そこを1回デコードしてURLを組み立て。

コメント