作ってるアプリでWEBの記事から本文抽出したい仕様があった。調べて見るとpython-extractcontent3というライブラリがあってタグ構造を見てルールベースで抽出してるっぽいのですが、そこそこ精度良いらしいので試してみます。

https://github.com/kanjirz50/python-extractcontent3

Windows10, WSL2環境でDocker, docker-composeを使って実装していきます。

プロジェクトルートを作る

$ mkdir extract-content
$ cd extract-content

ファイルはこんな構成です。

$ tree .
.
├── Dockerfile
├── docker-compose.yml
└── run.py

Dockerfile

FROM python:3
RUN pip install extractcontent3 requests

docker-compose.yml

version: '3'
services:
  python3:
    restart: always
    build: .
    container_name: 'python3'
    working_dir: '/root/'
    tty: true
    volumes:
      - ./:/root/

run.py

from extractcontent3 import ExtractContent
import requests

extractor = ExtractContent()

opt = {
    "threshold": 50,
}
extractor.set_option(opt)

res = requests.get('https://example.com')
html = res.text

extractor.analyse(html)
text, title = extractor.as_text()

print(title)
print(text)

ビルドするとなぜか怒られる

$ docker-compose build
Building python3
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/docker/utils/build.py", line 96, in create_archive
    with open(full_path, 'rb') as f:
PermissionError: [Errno 13] Permission denied: '/home/aharada/source/extract-content/.python_history'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/bin/docker-compose", line 11, in <module>
    load_entry_point('docker-compose==1.25.0', 'console_scripts', 'docker-compose')()
  File "/usr/lib/python3/dist-packages/compose/cli/main.py", line 72, in main
    command()
  File "/usr/lib/python3/dist-packages/compose/cli/main.py", line 128, in perform_command
    handler(command, command_options)
  File "/usr/lib/python3/dist-packages/compose/cli/main.py", line 292, in build
    self.project.build(
  File "/usr/lib/python3/dist-packages/compose/project.py", line 397, in build
    build_service(service)
  File "/usr/lib/python3/dist-packages/compose/project.py", line 380, in build_service
    service.build(no_cache, pull, force_rm, memory, build_args, gzip, rm, silent, cli, progress)
  File "/usr/lib/python3/dist-packages/compose/service.py", line 1084, in build
    build_output = builder.build(
  File "/usr/lib/python3/dist-packages/docker/api/build.py", line 159, in build
    context = utils.tar(
  File "/usr/lib/python3/dist-packages/docker/utils/build.py", line 29, in tar
    return create_archive(
  File "/usr/lib/python3/dist-packages/docker/utils/build.py", line 99, in create_archive
    raise IOError(
OSError: Can not read file in context: /home/aharada/source/extract-content/.python_history

原因を追求するのは面倒なので、適当にぐぐって見つかった対策をやってみる。.dockerignoreに怒られている対象のファイルを記述する

.dockerignore

.python_history

イケた。

$ docker-compose build
Building python3
Step 1/2 : FROM python:3
 ---> 4246fb19839f
Step 2/2 : RUN pip install extractcontent3 requests
 ---> Using cache
 ---> 9881e1590919
Successfully built 9881e1590919
Successfully tagged extract-content_python3:latest

Pythonのスクリプトを実行する。とあるレシピサイトの記事から本文抽出したらこんな感じになった。

$ docker-compose run python3 python run.py
サッパリ!トマトマリネ 作り方・レシピ | クラシル
 「サッパリ!トマトマリネ」の作り方を簡単で分かりやすいレシピ動画で紹介しています。 緑黄色野菜トマトで作った、さっぱりしたマリネです。そのまま食べても良いですが、レタスサラダの具としても、冷製パスタの ソースにしてもピッタリです。酸っぱくて硬いトマトなどは是非マリネに して召し上がってください。
調理時間:10分
費用目安:300円前後

実装的には問題なく出来たけど、本文抽出は期待していた結果にはならなかった。

おそらく一般的な記事は、1つの大きなセクションに本文が入っているけど、レシピは概要や材料、手順などが独立したブロックに記述されていることが多い。したがって、この仕組みは期待した通りには抽出出来ないっぽい。

こりゃ自分で実装しなきゃいかんか。