前回のつづき。
方法
1. 同一ソースの別カテゴリRSSを統合する。
stdin
でRSSリストを渡す- 1を指定したDBへ統合する
echo -e "RSS1\nRSS2\nRSS3" | ./run.sh /任意パス/news.db
RSSの統合はSQLite3ファイルを分けることで対応する。テーブルにsource
列を増やすと前回のように面倒になるため避ける。
もしRSSリストをファイルに保存しているなら、以下のようにする。
cat rss_list.txt | ./run.sh /任意パス/news.db
./run.sh
を./get_news.py
で動くようにしたほうが早いかもしれない。その場合はPythonでstdin
を取得する方法を調べる。
echo -e "RSS1\nRSS2\nRSS3" | python3 get_news.py /任意パス/news.db cat rss_list.txt | python3 get_news.py /任意パス/news.db
2. 重複チェックとHTML取得最少化
メモリを使って高速化やフラグメンテーション回避を狙う。
:memory:
→RAMディスクDB→ファイルDB
それぞれを以下のように別DBとしてattach
して名付けたものとする。
attach ':memory:' as m; attach '/RAMディスク/news.db' as r; attach '/永続ディスク/news.db' as f;
2-1. インメモリDB
:memory:
でインメモリDBを作り、そこで別カテゴリRSSを統合させる方法。
- 同一ソース源の別カテゴリRSSから取得したニュースを統合する:
:memory:
insert or ignore m.news ...
- DB内最新を取得する(統合ニュースから重複を削除):
./news.db
select max(published) from f.news;
- URLからHTML取得し本文抽出する
- DBへマージする:
:memory:
update m.news set body=? where published=? and url=?
- DBへマージする:
./news.db
insert or fail into f.news(...) select ... from m.news;
2-2. RAMディスクDB
さらにRAMディスクDBファイルを作る方法。ニュース取得のプロセス終了後でも、電源ON〜OFFまでの間に得たニュースだけを見れる。場合によっては、そこから選択したニュースだけをファイルDBへ登録させても良い。
- 同一ソース源の別カテゴリRSSから取得したニュースを統合する:
:memory:
insert or ignore m.news ...
- DB内最新を取得する(統合ニュースから重複を削除):
RAMディスク/news.db
select max(published) from r.news;
- URLからHTML取得し本文抽出する
- DBへマージする:
:memory:
update m.news set body=? where published=? and url=?
- DBへマージする:
RAMディスク/news.db
insert or fail into r.news(...) select ... from m.news;
- DBへマージする:
./news.db
insert or fail into f.news(...) select ... from m.news;
2-3. RSS用DB(RAMディスク)
上記までだと、本文抽出が完了するまでRSSが見れない。10分後かもしれない。もっと早く応答が欲しい。RSSだけ別DBにする。それをRAMディスクに配置する。
create table rss( published text not null, url text not null, title text not null, description text not null default '', UNIQUE(published,url) -- 記事の一意確認 );
2-4. 通知
本文が抽出されるには時間がかかる。完了したら通知して欲しい。
zenity --notification ...
フローを細かく
- インメモリDB
- ニュースが重複しうる複数のRSSをマージする
published
,url
,title
を取得する- それらが重複するものははじく
- ソートする:
order by published desc, url asc, id desc
- ニュースが重複しうる複数のRSSをマージする
- ファイルDB
- インメモリDBのうちファイルDBとの重複がないか探す
- 見つかれば、それ以前までのニュースのみ取り込む
[(published, url, title), ...]
のうち重複ニュースを切り捨てる
- RSS用RAMディスクDBに挿入する
[(published, url, title), ...]
- 見つかれば、それ以前までのニュースのみ取り込む
- 本文を抽出する
[(published, url, title, body), ...]
を生成する- ファイルDBに挿入する
- インメモリDBのうちファイルDBとの重複がないか探す
insert
には時間がかかるためexecutemany()
で一括挿入したい。だが、そのために全URLのHTML取得を完了させねばならない。そこに最も時間がかかる。
最初の1件目だけを、できるだけ早く見ることができれば嬉しい。だが、それだと挿入が遅くなる。RAMディスクに一時DBを作って、そこに1件ずつ挿入すればいいかもしれない。
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13 ※
- bash 4.4.12(1)-release ※
- Python 3.5.3
- SQLite 3.29.0 ※
- MeCab 0.996ユーザ辞書
$ uname -a Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux