いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Pythonメモ-68 (requests-html試してみた) (HTML Parsing for Humans, PyQuery, markdown, requests)

概要

Pythonの鉄板ライブラリ requests を作成した kennethreitzさんrequests-htmlというライブラリを公開されています。

github.com

requestsと同じく xxxx for Humans シリーズなライブラリ。やっぱり使いやすいライブラリでした。

markdownに変換できる機能が素晴らしいです。

Readmeみたら、大体の使い方がわかってしまうのですが、とりあえず自分でも使ってみたメモを残しておきます。

インストール

私の環境は、まだpipenvではなくて、condaです。

一旦、存在するかどうか探してみる。

⟩ conda search requests-html
Loading channels: done

PackagesNotFoundError: The following packages are not available from current channels:

  - requests-html

Current channels:

  - https://repo.continuum.io/pkgs/main/osx-64
  - https://repo.continuum.io/pkgs/main/noarch
  - https://repo.continuum.io/pkgs/free/osx-64
  - https://repo.continuum.io/pkgs/free/noarch
  - https://repo.continuum.io/pkgs/r/osx-64
  - https://repo.continuum.io/pkgs/r/noarch
  - https://repo.continuum.io/pkgs/pro/osx-64
  - https://repo.continuum.io/pkgs/pro/noarch
  - https://conda.anaconda.org/conda-forge/osx-64
  - https://conda.anaconda.org/conda-forge/noarch

無い。ってことで、pipから入れます。

⟩ conda create -n requests-html ipython
Solving environment: done

## Package Plan ##

  environment location: /Users/xxxx/anaconda3/envs/requests-html

  added / updated specs: 
    - ipython


The following NEW packages will be INSTALLED:

    appnope:          0.1.0-py36hf537a9a_0 
    ca-certificates:  2017.08.26-ha1e5d58_0
    certifi:          2018.1.18-py36_0     
    decorator:        4.2.1-py36_0         
    ipython:          6.2.1-py36h3dda519_1 
    ipython_genutils: 0.2.0-py36h241746c_0 
    jedi:             0.11.1-py36_0        
    libcxx:           4.0.1-h579ed51_0     
    libcxxabi:        4.0.1-hebd6815_0     
    libedit:          3.1-hb4e282d_0       
    libffi:           3.2.1-h475c297_4     
    ncurses:          6.0-hd04f020_2       
    openssl:          1.0.2n-hdbc3d79_0    
    parso:            0.1.1-py36hc90e01c_0 
    pexpect:          4.4.0-py36_0         
    pickleshare:      0.7.4-py36hf512f8e_0 
    pip:              9.0.1-py36h1555ced_4 
    prompt_toolkit:   1.0.15-py36haeda067_0
    ptyprocess:       0.5.2-py36he6521c3_0 
    pygments:         2.2.0-py36h240cd3f_0 
    python:           3.6.4-hc167b69_1     
    readline:         7.0-hc1231fa_4       
    setuptools:       38.5.1-py36_0 
    simplegeneric:    0.8.1-py36_2         
    six:              1.11.0-py36h0e22d5e_1
    sqlite:           3.22.0-h3efe00b_0    
    tk:               8.6.7-h35a86e2_3     
    traitlets:        4.3.2-py36h65bd3ce_0 
    wcwidth:          0.1.7-py36h8c6ec74_0 
    wheel:            0.30.0-py36h5eb2c71_1
    xz:               5.2.3-h0278029_2     
    zlib:             1.2.11-hf3cbc9b_2    

Proceed ([y]/n)? y

Preparing transaction: done
Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use
#
#     $ conda activate requests-html
#
# To deactivate an active environment, use
#
#     $ conda deactivate

一旦、conda で仮想環境作った後で、pipで入れます。

$ conda activate requests-html

一応、pip上にあるかどうかを検索

$ pip search requests-html | grep requests-html
requests-html (0.1.1)                                       - HTML Parsing for Humans.

オケ。てことで、インストール。

⟩ pip install -U requests-html                                                                                              (requests-html) 
Collecting requests-html
  Downloading requests_html-0.1.1-py2.py3-none-any.whl
Collecting pyquery (from requests-html)
  Downloading pyquery-1.4.0-py2.py3-none-any.whl
Collecting html2text (from requests-html)
  Downloading html2text-2018.1.9-py3-none-any.whl
Collecting parse (from requests-html)
  Downloading parse-1.8.2.tar.gz
Collecting requests (from requests-html)
  Downloading requests-2.18.4-py2.py3-none-any.whl (88kB)
    100% |████████████████████████████████| 92kB 2.0MB/s 
Collecting fake-useragent (from requests-html)
  Downloading fake-useragent-0.1.10.tar.gz
Collecting bs4 (from requests-html)
  Downloading bs4-0.0.1.tar.gz
Collecting lxml>=2.1 (from pyquery->requests-html)
  Downloading lxml-4.1.1-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl (8.7MB)
    100% |████████████████████████████████| 8.7MB 171kB/s 
Collecting cssselect>0.7.9 (from pyquery->requests-html)
  Downloading cssselect-1.0.3-py2.py3-none-any.whl
Collecting chardet<3.1.0,>=3.0.2 (from requests->requests-html)
  Downloading chardet-3.0.4-py2.py3-none-any.whl (133kB)
    100% |████████████████████████████████| 143kB 5.5MB/s 
Collecting urllib3<1.23,>=1.21.1 (from requests->requests-html)
  Downloading urllib3-1.22-py2.py3-none-any.whl (132kB)
    100% |████████████████████████████████| 133kB 5.3MB/s 
Requirement already up-to-date: certifi>=2017.4.17 in /Users/xxxx/anaconda3/envs/requests-html/lib/python3.6/site-packages (from requests->requests-html)
Collecting idna<2.7,>=2.5 (from requests->requests-html)
  Downloading idna-2.6-py2.py3-none-any.whl (56kB)
    100% |████████████████████████████████| 61kB 5.1MB/s 
Collecting beautifulsoup4 (from bs4->requests-html)
  Downloading beautifulsoup4-4.6.0-py3-none-any.whl (86kB)
    100% |████████████████████████████████| 92kB 4.8MB/s 
Building wheels for collected packages: parse, fake-useragent, bs4
  Running setup.py bdist_wheel for parse ... done
  Stored in directory: /Users/xxxx/Library/Caches/pip/wheels/b0/3b/37/4ab694a0d331a3cc487923ff9c3645d0f103e9cd4762065f77
  Running setup.py bdist_wheel for fake-useragent ... done
  Stored in directory: /Users/xxxx/Library/Caches/pip/wheels/07/04/1d/bbd8ba7d692add504b44552504b7df239bddf56aa3387cee2b
  Running setup.py bdist_wheel for bs4 ... done
  Stored in directory: /Users/xxxx/Library/Caches/pip/wheels/84/67/d4/9e09d9d5adede2ee1c7b7e8775ba3fbb04d07c4f946f0e4f11
Successfully built parse fake-useragent bs4
Installing collected packages: lxml, cssselect, pyquery, html2text, parse, chardet, urllib3, idna, requests, fake-useragent, beautifulsoup4, bs4, requests-html
Successfully installed beautifulsoup4-4.6.0 bs4-0.0.1 chardet-3.0.4 cssselect-1.0.3 fake-useragent-0.1.10 html2text-2018.1.9 idna-2.6 lxml-4.1.1 parse-1.8.2 pyquery-1.4.0 requests-2.18.4 requests-html-0.1.1 urllib3-1.22

結構いっぱい入りますね。

  • beautifulsoup4
  • pyquery
  • cssselect

たちが実行時に裏側で頑張っていると予想。

これでインストールは完了です。

軽く使ってみる

最初にimport

from requests_html import session

処理はこのsessionを起点に行うので、これだけimportしていれば基本使えます。

情報取得

次は、対象となる情報の取得です。今回は自分のブログの情報をちょこっと取得して遊んでみます。

r = session.get('http://devlights.hatenablog.com/')

html属性からリンク取得

session.get()で取得したオブジェクトのhtml属性からいろいろ取得できます。

Readmeにあるみたいに、リンクを取得してみます。

リンクの取得は、r.html.linksとすれば全部取得できます。

そのままやると、ちょっと件数が多いので3件のみ表示。

ちなみに、r.html.linksの結果はsetオブジェクトとなっています。

list(r.html.links)[:3]

['https://stackoverflow.com/questions/16869024/what-is-pycache',
 'https://docs.python.jp/3/using/cmdline.html#id1',
 'http://zetcode.com/lang/java/']

こんな感じ。楽ですね。

jqueryチックに要素を取得

pyqueryみたいに、 jquery なセレクタが使えます。

今回は、自分のブログの最近のエントリのリンクを抽出しようと思います。

Chromeのデベロッパーツール使うと、最近のリンクの部分には

recent-entries-title-link

という class が設定されている模様。

セレクタを指定して取得する場合は、r.html.find()を利用します。

print(r.html.find('.recent-entries-title-link', first=True))

結果はこんな感じ。ちょっと数が多いので、先頭のみ。

ちなみに、取得する際に first=Trueと指定すると最初の要素のみ返してくれます。

<Element 'a' href='http://devlights.hatenablog.com/entry/2018/02/25/212126' class='urllist-title-link recent-entries-title-link  urllist-title recent-entries-title'>

ちゃんと取得できましたね。

markdownに変換してもらう。

個人的に便利と思った機能。素晴らしい。

取得した要素に対して、markdown属性を指定すると、markdown形式にしてくれます。

recent_entries = [elem.markdown for elem in r.html.find('.recent-entries-title-link')]
for entry in recent_entries:
    print(entry, end='')

結果は以下のようになります。

[Pythonメモ-67 (JupyterLab試してみた) (JupyterLab is Ready for Users, conda, jupyterlab, PhosphorJS)](http://devlights.hatenablog.com/entry/2018/02/25/212126)

[Pythonメモ-66 (pycファイルの生成が行われないようにする) (PYTHONDONTWRITEBYTECODE,sys.dont_write_bytecode, __pycache__,pyc)](http://devlights.hatenablog.com/entry/2018/02/23/124719)

[zetcode さんのチュートリアルシリーズ (ZetCode turorials,沢山チュートリアルがあるサイト)](http://devlights.hatenablog.com/entry/2018/02/22/150217)

[C#のサンプルコードが沢山あるサイト (1000 C# Programs With Example Code andOutput)](http://devlights.hatenablog.com/entry/2018/02/22/133515)

[polacode (指定したソースコードを画像にしてくれる VS Code 拡張機能)(polanoid for your code, visualstudio code)](http://devlights.hatenablog.com/entry/2018/02/21/123728)

[carbon(ソースコードをキレイなハイライト状態で画像にしてくれるサイト)](http://devlights.hatenablog.com/entry/2018/02/20/122639)

[Pythonメモ-65 (send2trash) (ファイルをゴミ箱に捨ててくれるライブラリ,クロスプラットフォーム)](http://devlights.hatenablog.com/entry/2018/02/20/005539)

[Pythonメモ-64 (contextlib.redirect_stdout) (stdoutの矛先を一時的に変更する,redirect_stderr)](http://devlights.hatenablog.com/entry/2018/02/20/001449)

[いろいろな言語をREPLで試せるサイト (repl.it, C#, python, java, C++, Go,Ruby)](http://devlights.hatenablog.com/entry/2018/02/19/234327)

[Pythonメモ-63 (vscodeのpython拡張でlinterが選択可能になった) (visual studio code, selectlinter, Jan 2018
Release)](http://devlights.hatenablog.com/entry/2018/02/15/152401)

すばらしい。

サンプル

以下サンプルソースです。

"""
requests-html のサンプルです。
"""
from requests_html import session


def go():
    # セッション開いて、情報取得
    r = session.get('http://devlights.hatenablog.com/')

    # ページ内のリンク取得
    print(r.html.links.pop())

    # セレクタを指定して、jqueryチックに要素取得
    selector = '.recent-entries-title-link'
    entries = r.html.find(selector)

    # markdownに変換
    for entry in entries:
        print(entry.markdown, end='')


if __name__ == '__main__':
    go()

ほかにも、XPathなども普通に使えるみたいなので、今まではpyquery使ってたけど、当面 requests-html で良さそう。

kennethreitzさん、素晴らしいライブラリを公開してくれてありがとうございます。


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。