やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

https://docs.python.jp/3/contents.htmlから木構造になっている見出しのうち葉ノードだけを抜き出した

Python学習項目の一覧をつくるために。

成果物

GitHubBeautifulSoup.SelectLeafNode.201705150722

前回まで

スクレイピング

木構造の見出し

<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="whatsnew/index.html">What&#8217;s New in Python</a><ul>
<li class="toctree-l2"><a class="reference internal" href="whatsnew/3.6.html">What&#8217;s New In Python 3.6</a><ul>
<li class="toctree-l3"><a class="reference internal" href="whatsnew/3.6.html#summary-release-highlights">概要 &#8211; リリースハイライト</a></li>
<li class="toctree-l3"><a class="reference internal" href="whatsnew/3.6.html#new-features">新しい機能</a><ul>
<li class="toctree-l4"><a class="reference internal" href="whatsnew/3.6.html#pep-498-formatted-string-literals">PEP 498: フォーマット済み文字列リテラル</a></li>
...

見出しが木構造になっている。<li>の中に<ul>がネストしている。

葉ノードの見出しのみ取り出す

最小構成の見出しをすべて取り出したい。

tree = soup.find('div', class_='toctree-wrapper compound') # 2個目に取得できるものは空だから1個目を取る
leafs = tree.select('li:not(:has(ul))')

cssセレクタを使おうと思った。しかし以下のエラー。

NotImplementedError: Only the following pseudo-classes are implemented: nth-of-type.

どうやらスクレイピングツールBeautifulSoupはCSSセレクタの擬似クラスをnth-of-typeしか実装してないらしい。nothasなどは未実装。

仕方ないので要素を持っているか確認するメソッドを作った。for文がネストするとbreakするとき綺麗なコードが書けないからメソッドにする。

    def Has(self, parent, child):
        for c in parent.children:
            if child == c.name:
                return True
        return False

C#ならスマートに書けたのに。

所感

見出しだけでなく、全体を俯瞰したい。進捗表とか。でも木構造なのでテーブルで一覧できない。どうするか。