目次
前提
本記事は以下の環境で動作確認済み
要素 | バージョン |
---|---|
Debian | 9.1 |
pyenv | 1.1.3-7 |
python | 3.6.2 |
概要
Pythonを使ったことのない私が、pyenvを用いて現在の最新版であるPython3.6.2をインストールし、Wikipediaの特定ページからランダムにリンクを辿り続けるスクリプトを書いたお話。
Python3.6.2のインストール
pyenvについて
pyenvは、複数のPythonのバージョンを容易にインストール、切り替えを行うツール。Rubyのrbenvや、nodeのnvm,nなどと同じようなもの。
pyenvのインストール
以下ページをそのまま参考にした。
PyenvによるPython3.x環境構築(CentOS, Ubuntu) – Qiita
3.6.2のインストール
前述のページだと若干古いPythonを使っているので、pyenvを用いて以下のように3.6.2をインストール
$ pyenv install -v 3.6.2 $ pyenv global 3.6.2
確認
$ python --version Python 3.6.2
Python3入門
初Pythonだったのでまずは基本的な使い方を確認。以下のページが広く浅くしっかり丁寧だったので大変お世話になった。
Python3基礎文法 – Qiita
Wikipediaをクロールするスクリプト作成
概要
Pythonの基本を学んだので、手始めに、以下のような簡単なWebクロールスクリプトを書いてみる。
- 特定のWikipediaのページを開始地点とする
- 記事内の、他の単語へのリンク一覧を取得する
- ノイズとなるリンクを排除し、関連する単語へのリンクのみを取り出す
- 残ったリンク一覧から、ランダムに1件選出し、そのリンク先へ移動する
- リンク先のページタイトルを標準出力し、同様の操作を繰り返す
Wikipediaを使った連想ゲームのような物?
使用ライブラリ
調べてみると、PythonにはWebクロールのためのフレームワーク/ライブラリも充実してるようだが、今回はPythonのお試しも含んでいるので、HTTPにrequests、HTML/XMLパーサにBeautifulSoupというライブラリを用いることにする。
実装
そんなに長くないので先に全文
BASEURL = 'https://ja.wikipedia.org' # 指定したWikipediaページ内のaタグからランダムで一つ戻す def get_wiki_a_tag(url): response = requests.get(url) soup = BeautifulSoup(response.text, 'lxml') print(soup.find('h1').text) a_tags = filter( lambda a: 'href' in a.attrs and a.text and a.attrs['href'].startswith('/wiki') and a.attrs['href'].find('Wikipedia') and a.text.find('年') == -1, soup.select('.mw-parser-output p a') ) a_tags_list = list(a_tags) if not len(a_tags_list): print("end") sys.exit() return random.sample(a_tags_list, 1)[0] # 開始地点を設定 word = 'Python' url = f"{BASEURL}/wiki/{word}" # ランダムにWikipediaのリンクを飛び続ける while True: a_tag = get_wiki_a_tag(url) url = f"{BASEURL}{a_tag.attrs['href']}" time.sleep(1)
まず、以下の部分で特定URLのHTTPレスポンスを取得する。BeautifulSoupを用いることで、レスポンスのXML/HTMLをparseできるようにする。
response = requests.get(url) soup = BeautifulSoup(response.text, 'lxml')
関連する単語へのリンクは概ねdiv.mw-parser-output配下のp要素に含まれているので、その中のaタグの一覧を取得する。あくまで概ねなので正確ではない。
soup.select('.mw-parser-output p a')
ノイズとなるリンクはpythonのfilter関数で排除する。排除対象は以下の通り
- href属性が設定されてないaタグ
- テキストが設定されていないaタグ
- リンク先が/wiki で始まらないaタグ
- リンク先にWikipediaが含まれるaタグ(要出典、検証可能性など)
- テキストに「年」が含まれるaタグ(‘2010年’などの記事が頻出するため)
lambda a: 'href' in a.attrs and a.text and a.attrs['href'].startswith('/wiki') and a.attrs['href'].find('Wikipedia') and a.text.find('年') == -1,
randomパッケージのsample関数を用いて、aタグの一覧からランダムに一つ戻す。RubyだとArrayにsampleメソッドがあるのでちょっと不便だと思った。
return random.sample(a_tags_list, 1)[0]
動作確認
Pythonスタートでやってみたところ、初めのうちは良い感じだったが、トレインチャンネルあたりからおかしくなった。
もう一度。Googleから何故サウナ風呂につながるのか‥‥。
※確認した所、社内にサウナがあるらしい
試しに開始地点を阿部寛にしたらやたらとグローバリゼーションになった。阿部寛だしそんなものか。
所感
- とりあえず何かを作ることを通じてPythonに世界に飛び込んでみたが、まだまだ魅力は掴めてない。インデントブロックがPythonの特徴の一つだが、これもまだ見やすいとは思えない(インデント幅を4字にしたらまた違うかも)
- Rubyに慣れてて、Rubyが一番好きな分、Pythonとはウマが合わない可能性もあるが、もっと使ってみて自分に合うとこを見つけていきたい。
- 今回作ったスクリプト、ずっと眺めてられそう。