BeautifulSoupを使って、ブログ記事の情報をいろいろ絞り込んでみた
サーモン大好き、横山です。
今回はBeatifulSoupを使ってブログの記事情報を絞り込んで取得してみました。
準備
今回は、python3 + Beautiful Soup を使いました。
環境準備
$ pwd /tmp/bs4 $ virtualenv --python=`which python3` venv $ . venv/bin/activate $ pip install -U pip $ pip install beautifulsoup4
コード
- main.py
#!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import print_function, unicode_literals from bs4 import BeautifulSoup import re try: # for python3 from urllib.request import urlopen except: # for python2 from urllib2 import urlopen url = 'https://dev.classmethod.jp/etc/remote-work-bad-communication/' html_page = urlopen(url) soup = BeautifulSoup(html_page, 'html.parser') ### この部分に、 以下の「コード」の部分を貼り付けて実行しています ###
ブログの記事タイトルを取得する
ブログのタイトルを抜き出すために、h1タグを抽出します。
コード
title = soup.find('h1') print(title) print(type(title))
結果
<h1 class="single_article_title">[働き方] リモートワークにおけるコミュニケーションについて</h1> <class 'bs4.element.Tag'>
find 関数で見つけて来た要素をそのままprintするとHTMLタグ付で表示します。このobjectからtagのattributeやtextにアクセスするには次のサンプルのように値を取得します。
因みにfind関数は、該当するタグがなければ None
、複数該当する場合は最初にマッチした要素を返します。
コード
title = soup.find('h1') print(title) print(title.text) print(title['class'])
結果
<h1 class="single_article_title">[働き方] リモートワークにおけるコミュニケーションについて</h1> [働き方] リモートワークにおけるコミュニケーションについて ['single_article_title']
見出しを抜き出す
記事の見出しを抜き出すためにh2のタグを全て抜きだします。先程は find で見つけて来ましたが、今度は find_all 関数を使い全て取得します。
コード
for subheading in soup.find_all('h2'): print(subheading)
結果(2017/08/28時点)
<h2 id="toc-">リモートワークにおけるコミュニケーション</h2> <h2 id="toc-1">チャットは日常会話の延長ではない</h2> <h2 id="toc-2">よろしくないコミュニケーションの例</h2> <h2 id="toc--">[追記] 電話・音声通話について</h2> <h2 id="toc-3">まとめ</h2> <h2 id="toc-4">参照</h2> <h2>脚注</h2> <h2 class="name"><i class="icon-user"></i> <a href="https://dev.classmethod.jp/author/komuro-hiraku/" title="執筆者:小室 啓"><strong>小室 啓</strong> について詳しくみる <i class="icon-chevron-right"></i></a></h2> <h2 class="single_article_aside_sub_title"><i class="icon-folder-close"></i> 設定されているカテゴリー</h2> <h2 class="single_article_aside_sub_title"><i class="icon-tag"></i> 設定されているタグ</h2> <h2 class="single_article_aside_sub_title"><i class="icon-tag"></i> 同じタグが設定された記事</h2> <h2 class="title"> <a href="https://dev.classmethod.jp/etc/extreme-attendance-sapporo/">札幌オフィスにエクストリーム出社してみました</a> </h2> <h2 class="title"> <a href="https://dev.classmethod.jp/remote-work/skype-beginner/">[初心者向け]Skypeで知っておくと便利なこと[ちょっとだけ]</a> </h2> <h2 class="single_article_aside_sub_title"><i class="icon-calendar"></i> 開催予定のイベント</h2> <h2 class="title"> <a href="https://dev.classmethod.jp/news/akiba-aws-170831/">【8月31日(木)東京】「AKIBA.aws 第1回 基礎編」を開催します</a> </h2> <h2 class="title"> <a href="https://dev.classmethod.jp/news/jobfair-170905/">【9/5 東京】クラスメソッドの会社説明会を開催します。〜大阪・札幌からリモート参加もOK〜</a> </h2> <h2 class="title"> <a href="https://dev.classmethod.jp/news/jobfair-170920-osaka/">【9/20 大阪】クラスメソッドの会社説明会を開催します。</a> </h2> <h2 class="title"> <a href="https://dev.classmethod.jp/news/developers-io-2017-world-osaka/">9/23(土)『Developers.IO 2017 WORLD in 大阪』を開催します!</a> </h2> <h2 class="title"> <a href="https://dev.classmethod.jp/news/developers-io-2017-world-nagoya/">9/28(木)『Developers.IO 2017 WORLD in 名古屋』を開催します!</a> </h2> <h2 class="option_nav_popup_section_title"><i class="icon-folder-open"></i> カテゴリー一覧</h2> <h2 class="option_nav_popup_section_title"><i class="icon-tags"></i> タグ一覧</h2> <h2 class="option_nav_popup_section_title">絞り込むカテゴリーを選択</h2>
余分な情報も取れたので、もう少し絞り込みます。
コード
for subheading in soup.find_all('h2', id=re.compile('toc-.*')): print(subheading)
タグ名の他に、id名に toc-.*
の正規表現でマッチするものと追加しました。
結果
<h2 id="toc-">リモートワークにおけるコミュニケーション</h2> <h2 id="toc-1">チャットは日常会話の延長ではない</h2> <h2 id="toc-2">よろしくないコミュニケーションの例</h2> <h2 id="toc--">[追記] 電話・音声通話について</h2> <h2 id="toc-3">まとめ</h2> <h2 id="toc-4">参照</h2>
いい感じにしぼりこめましたが、「脚注」は id 指定されてないので抜けてしまいました。
コード
for subheading in soup.find('article').find_all('h2'): print(subheading)
切り口を変えて、記事ブロック ( <article>
) tagで絞り込んでから、h2でさらに絞り込む
結果
<h2 id="toc-">リモートワークにおけるコミュニケーション</h2> <h2 id="toc-1">チャットは日常会話の延長ではない</h2> <h2 id="toc-2">よろしくないコミュニケーションの例</h2> <h2 id="toc--">[追記] 電話・音声通話について</h2> <h2 id="toc-3">まとめ</h2> <h2 id="toc-4">参照</h2> <h2>脚注</h2>
目的の見出しを絞り込めました。
og:image に指定している画像URLを取得する
<head>
タグの metaタグにある
<meta property="og:image" content="https://cdn-ssl-devio-img.classmethod.jp/wp-content/uploads/2015/12/communication-320x256.png" />
の https://cdn-ssl-devio-img.classmethod.jp/wp-content/uploads/2015/12/communication-320x256.png
を取得する
コード
og_img = soup.find('meta', attrs={'property': 'og:image', 'content': True}) if og_img is not None: print(og_img['content']) else: print('!!not found og:image tag!!')
'content': True
は attribute にcontentが存在するものを取ってくるようにしています。
前の見出しのh2の脚注だけ除きたい場合は、 find_all('h2', id=True)
とやればできます。
結果
https://cdn-ssl-devio-img.classmethod.jp/wp-content/uploads/2015/12/communication-320x256.png
まとめ
BeatifulSoupのObject作って、find、find_allを駆使すると、簡単にHTMLページの欲しい情報を取得できました。
階層が深い場合でも、調べたい要素がタグ名やid名、class名が分かれば、狙いうちでその要素を抜き出せます。
例えば、とあるページの画像URLだけ抜き出したいとかは、 [img['src'] for img in soup.find_all('img') if img.get('src', None) is not None]
とか雑に呼ぶとそのページのimgタグを使用している画像URLを取得することができます。