今日も微速転進

ここではないどこかへ

今週のふりかえり(2018年6月第1, 2週)

早く梅雨が明けますように。

今週の学び

よくわからないが以前から雇われたくないという思いが強かった。どうやらその正体は急かされたり妥協を強要されたりと自分を尊重してもらえないことへの反発っぽい。

マイペースでやる分には労働を苦痛に感じないし、気分よく仕事ができる。スケジュール的に厳しくても何かしら自分の意見が採用される状況であれば苦痛に感じない。

逆言うと、ある程度裁量が与えられていないと全然駄目。自分の意見なりアイディアが採用されるかどうかでものすごくやる気に差が出る。なかなか都合のいい職場はないだろうからやはり自分で自分の仕事を創るしかなさそう。

メールサービス

Tutanotaというメールサービスの有料プランならさくらのメールボックスの代替になりそう。

サービス契約前にもっと調べておけばよかったね。激しく後悔。

参考:Alternatives to Google Products (Complete List) | Restore Privacy

その他・ノウハウなど

はてなブログのMarkdownとシンタックスハイライト

バッククォート3つのあとにbashではなくshか。

他のMarkdown対応サイトだと、shell-sessionとか使えるんだけど、はてなは駄目なんだよね。

はてなブログ、地味に改善してくれるんだけど、どうも遅いよね、仕事が。

はてなブログの有料プラン、継続しない方向で。

tmuxとsshと色

tmuxを使ってssh接続先ごとにターミナルの背景色を変更する | 俺的備忘録 〜なんかいろいろ〜

Python Tips

Intermediate Python — Python Tips 0.1 documentation

あとで読む。

GitHub Markdown

expand me!

gist.github.com

面白い。

テキストの前処理

mae.chab.in

現実はいろいろと泥臭いノウハウが必要ではないかと思うけど。

前処理大全[データ分析のためのSQL/R/Python実践テクニック]

前処理大全[データ分析のためのSQL/R/Python実践テクニック]

今週見つけた・試したソフトウェア or サービス

いいかげん、Hugoでサイトを作ろうと思ったけど、カテゴリ名やタグと実際のURL文字列*1のマッピング(slugとかtag mappingとか)ができないみたいなのでHexoに。

テーマはHugoの方が良さげなやつがあったり、トータルでは魅力的だったんだけど、その機能の関係で諦めた。

各種エンコード変換サイト

エンコードマニアックス

これは便利そう。

Visual Studio Code

Atomはやっぱり重いので移行開始。

日記を書く用途がメインだけどPythonのコードを書くときはこっちにしようかと画策中。

プログラミング用のエディタとしてはVimがいいと思うのだけど、日本語の入力に関する不便さはどうしようもなくて、日記のたぐいとかちょっとしたメモはAtomで書いていた。フォルダを開いて複数ファイルにすんなりアクセスできるのは大きい。

便利な機能が標準搭載で、最低限のカスタマイズで十分に使い物になるというのは大きい。

VimにしろEmacsにしろ、カスタマイズ手段がありすぎるし、流行り廃りがあるのは流石に勘弁。適当にググっていて今まで知らなかったプラグインに遭遇したりというのは面倒。自分の知らない未知の便利な機能があるかもしれないという不安感があって、VimもEmacs含めてエディタのカスタマイズは食傷気味。

そういう理由でRailsも好きじゃない。奥が深すぎて、もっとスマートな書き方があるんじゃないのか、この書き方でいいのかって不安になる。

某雑誌の特集のテーマがエディタだったりするとやるせない気分になる。 自分がおじさん化している可能性については否定しない。

Netlify

www.netlify.com

ようやく開始。詳細は別途。

Google Chrome 拡張

chrome.google.com

確かに古い記事を無視したいときはあるのでインストールしてみた。結構検索結果がガラリと変わって興味深い。

電子書籍販売サイト

honto.jp

新規登録で30%オフクーポンとかいろいろやっている。

出版社の公式サイトで電子書籍を買うよりも、個別の電子書籍販売サイトのほうが安いとかやめようよ。

パソコンのメーカー公式通販サイトが小売店に遠慮して値下げできない一方で、量販店は叩き売り同然っていうかつての悲劇を思い出さずにいられない。

なにか公式固有の工夫をするか、自社の直販の電子書籍はやめて一元化すればいいのに。

単色系のカバー画像画像生成。

cover.nemoinc.jp

公開直後からどんどん機能が追加されている。

作者さんのブログ。

noteやブログで使えるカバー画像をサクッとつくれるサービスを公開しました | TECHNICAL CREATOR

NameCheap

WhoisGuardが無料化したらしい。既存のユーザーで有効にしている場合はなにかアクションがいるのかどうかは不明。次回更新タイミングになにかすればいいのか?

ソフトウェア開発関連

PythonとProtocol Buffer

便利サービス

curl.trillworks.com

www.gitignore.io

ツール系

ソシャゲエンジニアの自分が開発MacBookにインストールしているアプリやら設定やら

肩書は余計だと思うのだが。

気になったもの

地図関連

オーサグラフ地図というものがあるそうな。メルカトル図法の誤差の話は知っていたけど、代替案の存在は知らなかった。

ただ、理屈がよくわからん。

球を正四面体に変換ってのがどうもよくわからない。

それぞれのキーがLCDになったキーボード

www.infinitton.com

MacBook ProのTouch Bar的なもの。OSに統合されているかと言うのは重要だけど、汎用性では断然こっちのほうがいいのでは。

マラケシュ条約関連

あまり報道されてないのか、話題になってないみたいだけど。

フェアユースとは違う。政府の認定した組織を経由しないといけないので不自由だけど、大きな進歩。

このまま締結されるのかな。

やっぱりTwitterとGoogle入手+RSSリーダーという情報収集スタイルはちょっと無理があるかな。

政治的理由で選り好みしているのでしょうがない。

野党は欠席、と。こういうのは地味に響くと思う。

参考:参議院本会議 - ながみね誠ホームページ

面白いと思ったサイトなど

ImageMagickeを使ったスクリプト

Fred's ImageMagick Scripts: TEXTCLEANER

Tesseract のGoogle Groupで紹介されていたもの。商用利用不可。まだ試していない。

出版関係者のサイトなど

画像のホスティング(共有)サービス

Cloudup

面白そうだが現状では新規ユーザーの募集は停止中らしい。招待コードがあればアカウントを作れるっぽい。

ちょっと太っ腹すぎるのかな?

読んだ本

SD総集編

Software Design総集編【2013~2017】

Software Design総集編【2013~2017】

適当にピックアップしたバックナンバーをいくつか。

購入したもの

HTML5&CSS3デザイン 現場の新標準ガイド

HTML5&CSS3デザイン 現場の新標準ガイド(特典PDF付き)

HTML5&CSS3デザイン 現場の新標準ガイド(特典PDF付き)

著者Webサイト:『HTML5&CSS3デザイン 現場の新標準ガイド』について – E BISUCOM TECH LAB

HTML5とCSS2/3はちゃんと勉強してないので今更ながら。

なかなか良書っぽい。

「書名+特典」でググると特典のPDFがヒットするんだけど、(アクセス制御的な意味で)大丈夫?

購入者特典の申込みフォームは以下。

book.mynavi.jp

日立の掃除機用紙パック

通常のものより高性能らしい。とりあえず実戦投入中。花粉アレルギーの人に使用感を聞いてみたい。

【やじうまミニレビュー】1枚700円する日立掃除機用紙パックの実力 - 家電 Watch

購入後の感想といきたいところだけど、交換直後なのでまだなんとも言えない。

雑誌

現代思想 2018年3月号 特集=物流スタディーズ ―ヒトとモノの新しい付き合い方を考える―

現代思想 2018年3月号 特集=物流スタディーズ ―ヒトとモノの新しい付き合い方を考える―

この雑誌の購入は初。ものすごく周回遅れだけどなかなか面白い。

経由:出版状況クロニクル120(2018年4月1日~4月30日) - 出版・読書メモランダム

調味料

ユウキ 化学調味料無添加のあごだし 110g

ユウキ 化学調味料無添加のあごだし 110g

顆粒タイプなのでラク。出汁をとったあとのゴミの始末がないのは非常に助かる。

アウトプット

今週の気づき&まとめ

まあぼちぼちですかね。生産性の低さはともかく、アウトプットがゼロではないのは評価していいはず。

2週おきだと文字数が増えてどうかな、と思うので毎週ふりかえり記事を書くスタイルに戻そうかと思います。

*1:表示は日本語だけどURLは英数字、とか

またひとつ、パンドラの箱が開いた

小説家のSNSでの過去の発言が原因で声優降板、アニメ化企画が中止になったそうな。しかも出荷停止とかいう話も出ている。


これの事件、いろいろまずいと思う。以下、順不同。

  1. (明言していないが)作者の過去の言動というな理由で降板という実例ができてしまった
  2. 某大陸の国家と某半島に(資本的な理由で?)配慮せざるを得ないという現状
  3. 気に入らない作品に対して、作者のあら捜しという手法が一般に認知されてしまった
  4. 特定の国家へのヘイトスピーチだけが注目されるリスク(ダブルどころかマルチスタンダード)
  5. 国内市場より規模の大きい海外市場を重視することを公然と表明*1
  6. 法的根拠もなく、SNSという公共の場所とはいい難い場所での個人の過去の言動*2を問題視
  7. ヘイトスピーチ、差別表現とも主観による判断*3でしかない

最初は声優の降板について書こうと思ったのにまたたく間に事態が急展開している……。

大手マスコミまで報道する始末……。人材派遣会社の会長が経済政策に口出ししているような、利益相反行為*4を批判すべき。

「7. 」は別の機会に記事を書きたいと思っている。


そもそも、ヘイトスピーチ云々は主観の問題。ヘイトスピーチを判定するプログラムを書けるわけではない。
言論封殺とか思想統制になりかねないので個人的にヘイトスピーチ規制法は悪法だという見解。

デマはデマ、誹謗中傷は誹謗中傷として批判すればいい。

そもそも、Twitterにはミュート機能とブロック機能でフィルタできるでしょ。

大前提として、ネットに作品を投稿している人物は公人じゃないよね。そしてSNSは公共の場所とはいいきれない。それなのにアニメ化中止、出版停止って 問題がありすぎる。作者本人が作品の修正を希望しているらしいけど、それ、炎上で弱気になって判断力の低下している状況での意思表示、ではないでしょうか。

作者の人格に問題があるかと作品は無関係、ということにしておけば良かった。小説に限らず、芸術系のセンスなり才能のある人は結構癖が強いひとが多いから、そういうことにしておかないと、収拾がつかない。

世間的に評価されている作品で、作者の人格に問題ないっていい切れるものがいくつあるのか。

差別表現が悪いのは同意する。ただ、領海侵犯を繰り返したり、恫喝外交を繰り返す国に不快感、嫌悪感を持たないほうが異常だとおもうけどね。
たいていどこの国も何かしらの悪行を働いているはず。

海外の人間が日本の悪気を言っても知らぬ存ぜぬ報道せずで、こういうときだけ誰かが馬鹿騒ぎする。まあ外国語を理解できないからそういううるさい人は気づかないんだろうけど。


出演拒否(降板)問題について。はっきりとした理由は明らかにしていないとはいえこういう出演拒否という実績があると、他の作品に出演したときに「あの作品には出演したのにこっちの作品には出演するのか?」という批判にさらされるのはほぼ確定。

何よりも、日本国内のファンからのイメージよりも、海の向こうのファンからのイメージを大事にすということをはっきり表明している。

自国のアニメ産業を有利にするために、特定の作品の表現にいいがかりをつけてくる可能性が増した。徳川家康の「国家安康」「君臣豊楽」という過去の事例がある。


作者のヘイトスピーチでイメージダウンするというなら、偏向報道のテレビ局の番組に出演していてもイメージダウン、ですよね?
某報道番組のスポンサーとかね。まあいつものダブル(マルチ)スタンダード 。

他国の人間にどう思われるか、気にしすぎ。翻訳しなければいいのに。


何より重要なのは表現の自由。少なくとも某大陸の国に対する日本のアドバンテージがまさにこれ。敗戦という代償を払って得た伝家の宝刀。

目先の売上のためにせっかくの表現の自由を手放そうとしている。まあその幼稚なところが実に日本的。表現の自由を守るために戦っている人はいても、 そもそも人権に関して何かを「勝ち取った」ことがほとんど無いからしょうがないのかな。

ヘイトだの差別だのと騒ぐけど、騒いでる本人はその小説読むの? アニメ見るの?

個人的には偏向報道の日本のマスコミのほうがよっぽど不快。だからテレビは買ってないし、これからも買わない。

一部の人の心情を害したっていうけど、件の小説の作者のTwitterアカウントをフォローしていたの?

わざわざ貴重な時間を使って、件の小説を熟読したの?

まさかお金を払って差別発言をするような作家の小説をお買い上げ?

社会的影響力のあるマスメディアの偏向報道ほうがよっぽど問題。

自分が普段見向きもしない物に、言いがかりつけて騒いでどうするのか。

しかもすでに販売されている小説を購入した読者よりも今後の海外展開と関係者のイメージを優先って。


資本の力の前に膝をつくのは仕方がないとしても、外部からの抗議に屈したってのは非常にまずい。今後もこういう事例はどんどんでてくる。
国内資本ならともかく、海外資本ってのは非常にまずい。国際問題としてとりあげて来る可能性もあるし。

間違いなく、これいろんなところに波及する、きっと。過去の言動(というか黒歴史)を気にして思い切った行動を思いとどまる人も出てくるだろうから将来の作品にも影響する。どんどん社会が息苦しくなっていく。まさにパンドラの箱

そういえばパンドラの箱、比喩表現とはいえたくさんあるよね。


そもそも、件の小説、そんなに面白かった? 何でもアニメ化しようっている粗製乱造気味だとおもうんだけど、アニメ業界、ホントに大丈夫? しかも出版元、ホビージャパンか。ピックアップする作品のセンスがあまり良くない印象。


P.S. 出演する側にも当然、客を選ぶ権利はある。それが本当に本人の意志なら問題ない。ただ、キャストを公表してから外部の指摘でってのはまずい。非常にまずい。


「表現の自由」の守り方 (星海社新書)

「表現の自由」の守り方 (星海社新書)

アニメを仕事に! トリガー流アニメ制作進行読本 (星海社新書)

アニメを仕事に! トリガー流アニメ制作進行読本 (星海社新書)

*1:これは商売だから仕方がないけど後出しは駄目

*2:法には触れてないよね?

*3:差別評価どうか判定するのは一体誰か

*4:もっといい表現があったけど忘れた

ブログのカスタマイズについての備忘録

一部のカスタマイズはPro化(有料プラン)が前提です。このブログはあと2週間でProではなくなりますが……。

下書き状態で放置していたので情報の鮮度はいまいちです。あしからず。

テーマを変えたり自動広告を試したり試行錯誤中です。

使用しているテーマ

たまに自分が使用しているテーマ(公式以外)が何だったか忘れる。

Innocent - テーマ ストア

Minimalism - テーマ ストア

はてなブログにアクセスした状態で、下記のURLにアクセスすると確認できる。

http://blog.hatena.ne.jp/-/store/theme/-/installed

見出しのカスタマイズ

参考にした訳ではないですが、以下のページもすごいと思います。

ガーリーなデザインの見出しのCSS はてなブログへコピペで使えます。 - Minimal Green

Adsense

レクタングルの広告を2つ並べるサイトが多いのでやってみる。注意点は、レスポンシブのテーマの場合は、スマートフォン用の表示の際に、広告が縦に2つ並ぶと規約違反になるという点。

いわゆるダブルレクタングルについては方法が3通りあって、

  • tableタグ
  • リスト要素タグ+CSS
  • divタグ+CSS

最初のtableタグはスマートフォンで表示した時に2つ目の広告が横にはみ出すので不適。PC専用ならあり。

CSSの場合はfloat: left;よりも、display: inline-blockを使う方が段落ちしないので良いと思う。

広告配置について

広告の配置に関するポリシー - AdSense ヘルプ

Adsenseの広告ユニットの数については緩和されているけど、配置については制約あり。

その他

【はてなブログ】関連記事のデザインカスタマイズ方法とサンプル19選


おしまい。

目の手術から3年経過

f:id:atuyosi:20180605190835j:plain:w480

a244.hateblo.jp

若年性白内障の手術してからまる3年経ちました*1

もう3年、です。石の上にも三年といいますが、気がついたら三年です。

特に問題がないので書くことに困る状況……。

目に関しては問題なし。問題は耳の方ですね。右耳の耳鳴りと聴力低下。

手術そのものに関しては過去記事参照ということで。  

a244.hateblo.jp

a244.hateblo.jp

目の手術という一種の対症療法で「ものが見えない」という問題は解決した訳ですが、若くして白内障になるような、体質というか習慣というか、根本原因は残ったまま。その結果が目の次が耳に来たのかな、とか思ったり。

病気も障害もなりたくてなっている訳ではないんですが(当たり前)、何かの深層心理*2が病気という形で具象化しているのかなと思うこともあります。

もともと鼻炎持ちなので鼻から目、耳という東洋医学的な理解で無理やり自分を納得させています。

耳に関しては内向型のインドアタイプなので耳鳴りさえ悪化しなければ「まあいいか」って感じですね。

おしまい。

その白内障手術、待った!  ―受ける前に知っておくこと―

その白内障手術、待った! ―受ける前に知っておくこと―

人生が変わる白内障手術

人生が変わる白内障手術

*1:正確には右目の手術から

*2:あまり人と関わりたくないとか雇われたくないとか

財務省の公開した交渉記録PDFをいじる その2(本文データのOCR etc.)

過去記事の続き。やはり実際のデータでデータ処理をやるのは勉強になります。

……お金になるかは別にして、Pythonという言語の習熟度は向上しているはず。

a244.hateblo.jp

方針

過去記事の方針を踏襲。

  1. 目次のPDFから交渉記録(応接記録)を機械可読(Computer Readable)な形式に変換
  2. マスク無しのPDFを画像化、再度PDFに変換して過去記事で紹介したAPIOCR
  3. 目次のページ番号から必要なページを割り出して、OCR結果を分割、どうにして添付資料のページを除去
  4. どうにかしてMarkdown
  5. 静的ページジェネレーターでWebページ化

この記事の対象は上記の「2. 」と「3. 」です。

OCR処理

といってもデータさえ用意すれば過去記事のスクリプトを実行するだけです。

画像の抽出

せっかくなので黒塗りなしの方で行ってみましょう。

a244.hateblo.jp

一部のページで画像が複数含まれているので注意する。

  • 20180523p-2.pdf: p.68, p.69, p.244
  • 20180523p-4.pdf: p.82

PDFファイルがorigin_pdfというディレクトリ配下にあるとしていう前提。出力先のディレクトリはunmaskable_pdf/images_1/outupt_{1,2,3,4}

$ mkdir images_{1,2,3,4}
$ pdfimages -p -png  origin_pdf/20180523p-1.pdf unmaskable_pdf/images_1/outupt_1
$ pdfimages -p -png  origin_pdf/20180523p-2.pdf unmaskable_pdf/images_2/outupt_2
$ pdfimages -p -png  origin_pdf/20180523p-3.pdf unmaskable_pdf/images_3/outupt_3
$ pdfimages -p -png  origin_pdf/20180523p-4.pdf unmaskable_pdf/images_4/outupt_4

実際はシェルスクリプトのようにforでループ。

#! /usr/local/bin/bash

for i in 1 2 3 4 ; do
    echo $i
    pdfimages -p -png  origin_pdf/20180523p-$i.pdf unmaskable_pdf/images_$i/outupt_$i
done

画像をPDFに変換・結合

convertで各ページをPDFにしてmutoolで結合。事前に上記のダブっているファイルを退避しておくこと。

#! /usr/local/bin/bash

for i in 1 2 3 4 ; do
    TEMP_DIR=unmaskable_pdf/temp_${i}
    OUTPUT_PDF=output_${i}.pdf

    for j in `ls -d unmaskable_pdf/images_$i/*.png  | sort -V`  ; do
    #    echo $j
    filename=$(basename $j .png)
    echo ${TEMP_DIR}/$filename.pdf
    convert $j -negate -quality 100 -units PixelsPerInch -density 72x72  ${TEMP_DIR}/$filename.pdf

    done

    echo merge to ${OUTPUT_PDF}
    ls -d ${TEMP_DIR}/*.pdf | sort -V | tr '\n' '\0' | xargs -0 -J% mutool merge -o ${OUTPUT_PDF} %
done

mogrifyコマンドを使うべきだったかな。

参考:大量の印刷用画像をウェブ用に変換する方法 - クックパッド開発者ブログ

一括OCR

過去記事参照。

a244.hateblo.jp

もう一度mutoolでPDFを結合。

$ mutool merge -o gen_pdf/fullset.pdf gen_pdf/output_1.pdf gen_pdf/output_2.pdf gen_pdf/output_3.pdf gen_pdf/output_4.pdf

生成したPDFのページ数をチェックしてGoogle Cloud Storage のバケット*1にアップロードしてOCR

$ python3 ocr_and_wait.py --gcs-source-uri gs://<bucket-name>/fullset.pdf --gcs-destination-uri gs://<bucket-name>/output_unmasked/

<bucket-name>の部分は適宜修正。

JSON分割

バッチサイズの数字を"5"にしているので下記のスクリプトで扱いやすいようにJSONを分割する。

#! /usr/bin/env python3
# encoding: utf-8
# busrst:py


from google.cloud import vision_v1p2beta1 as vision
from google.protobuf import json_format
from google.protobuf.json_format import MessageToJson

import json
import pathlib
from natsort import natsorted



def burst_json(input_path, output_path="./output"):

    input_pl = pathlib.Path(input_path)

    filelist = list(input_pl.glob('*.json'))
    for file_path in filelist:
        print(file_path)

        with file_path.open(mode='rt',encoding='utf-8') as jfp:
            str = jfp.read()

            response = json_format.Parse(str, vision.types.AnnotateFileResponse())

            for i, res in enumerate(response.responses) :
                page_num = res.context.page_number

                print("{0} {1} {2}".format(file_path.name, i,page_num ) )

                filename = "output_json_{0}.json".format(page_num)

                output_pl = pathlib.Path(output_path, filename)

                with output_pl.open(mode='w',encoding='utf-8') as output:

                    serialized = MessageToJson(res)

                    temp = json.loads(serialized)
                    json.dump(temp, output, ensure_ascii=False, indent=2, sort_keys=True, separators=(',', ': '))

if __name__ == '__main__' :

    input_path = "./output_unmasked/"
    output_path = "./ocr_unmasked/" 

    burst_json(input_path, output_path)

入力となるJSONのあるパスと出力先のパスがハードコードなのは面倒だから*2

タブ区切りテキストののパース

前回作成したTSVと、上記のOCR結果のJSONデータを用いて、交渉記録のエントリ番号(通し番号)に対応するページの範囲を割り出します。

財務省の公開した国有地の取引に関する交渉記録の目次PDFから抜き出した日付とページ番号の対応表(2018年5月) · GitHub

OCR結果がいまいちだったり、そもそも書式が微妙という問題の関係でスマートには行きません。とりあえずスクリプトは以下のように。

  1. 前回作成したタブ区切りテキストをcsvモジュールで開く
  2. リストとしてデータを読み込む(1行スキップ)
  3. 読み込んだデータを対象にforループを実行(217日分)
  4. それぞれの行についてページ番号を取得し、そのページ番号から最終ページまで繰り返す
  5. 対応するページ番号のファイルを開いて「以上」という文字列*3を探す
  6. 見つかったらそのページを終了ページとみなす
  7. 見つからなければ次。もし次のページ番号が「2. 」で読み込んだリストにあればそこでループ終了
  8. すべてのエントリについて繰り返す(「3. 」に戻る)

細かい条件判定はコードを参照。

#! /usr/bin/env python3
import csv
import pathlib
import json

import re
import collections
import sys

tsvfilename = "negotiation-history.tsv"
tfp = open(tsvfilename)

reader = csv.reader(tfp, delimiter="\t")
next(reader) # 見出し行をスキップ

start_page_index = [row for row in reader ]

black_list = { 191: 198, 318: 320, 850: 852, 945: 945}


# 分割済みのJSONファイルの格納パス
pl = pathlib.Path('./ocr_unmasked')

# Python 3.6系以降では実装仕様として辞書のキーの順序が保存されるので通常の辞書でも良いが、一応
page_range_list = collections.OrderedDict() 

p_finish_word = re.compile('以\s*上\s+') # スペースの有無に関わらずマッチする

# 最後のエントリの開始ページ番号
last_page_index = int(start_page_index[-1][1])

for node in start_page_index :
    date_st = node[0]
    idx = node[1]
    for i in range(int(idx),957+1):
    
        json_filename = "output_json_{}.json".format(i)
        
        path = pl / json_filename
        
        with path.open(mode='rt',encoding='utf-8') as fp:
            json_data = json.load(fp)
        
            text = json_data['fullTextAnnotation']['text']
                       
            if p_finish_word.search(text) :
                print("{0}: start {1}, end of article: {2}".format(path, idx, i), file=sys.stderr)
                
                if not str(idx) in page_range_list:
                    page_range_list[str(idx)] =  [idx, i , date_st]
                else:
                     page_range_list[str(idx) + "_1"] =  [idx, i , date_st]
                
                break

            if i + 1 in start_page_index or i == last_page_index :
                
                if idx in black_list :
                    
                    if not str(idx) in page_range_list:
                        page_range_list[str(idx)] = [idx, black_list[idx] , date_st]
                    else:
                         page_range_list[str(idx) + "_1"] = [idx, black_list[idx] , date_st]
                
                    
                    print("{0}: start {1}, End marker not found!, but in black list...{2}".format(path, idx, black_list[idx]), file=sys.stderr)
                else:
                    if not str(idx) in page_range_list:
                        page_range_list[str(idx)] =  [idx, i , date_st]
                    else:
                        page_range_list[str(idx) + "_1"] =  [idx, i , date_st]
                
                    print("{0}: start {1}, End marker not found!, so use current page number...{2}".format(path, idx,i), file=sys.stderr)

                break
            
#print(page_range_list)


output_tsv = pathlib.Path("./entries_page_range.tsv")

with output_tsv.open('wt', encoding='utf-8') as ot :
    tsv_writer = csv.writer(ot, delimiter="\t")

    for entry_id,key in enumerate(page_range_list, 1) :
        #print(page_range_list[key])
        start_num = page_range_list[key][0]
        end_num = page_range_list[key][1]
        entry_date = page_range_list[key][2]

        record = [ "{0:03}".format(entry_id), start_num,end_num, entry_date]
        tsv_writer.writerow(record)

成果物

OCR結果のJSONは数が多いのでともかくとして、最終的なページ番号対応表(見出し行つき)。

財務省の公開した国有地の取引に関する交渉記録の目次PDFから抜き出したエントリ番号とページ範囲、日付の対応表(2018年5月) · GitHub

反省点

  • バッチサイズを1にしておけば余計な手間がいらなかった
  • めんどうだけどコマンドライン引数でファイルのパスを指定するように(コードスニペットを用意しておくとか)
  • 遊んでないで他のことをやるべきでは?

続きます。

頑張ってJSONからMarkdownかHTMLにしていきます。

実践 Python 3

実践 Python 3

*1:適当に作成

*2:怠惰ですいません

*3:空白を含む場合なども考慮する

広告