Google Patentsを翻訳してみる。
企業で研究者をやっていると、特許調査と無縁ではいられません。[1]
日本語の特許ならまだ良いのですが、外国語で書かれた特許を読む場合もあります。
それも、外国語の特許を100件単位でチェックしなければならない事態になるとしたら、仮にその言語が得意であっても、大抵の人は嫌になると思います。
実際に、そのような事態に巻き込まれた私は、時短のために特許の請求項だけ抽出して翻訳する作業をpythonで自動化していました。
juliaでも同様のことができたので、やり方を紹介したいと思います。
ちなみにGoogle Patentsをパースして、Google翻訳するというGoogle先生に完全におんぶにだっこのプログラムです。[2]
[1] | 特許を書くこととも無縁ではいられません。 |
[2] | chromeの右クリックメニューで翻訳すればいいのに、という突っ込みは無視します。 |
流れ
プログラムの流れを図示すると、以下のようになります。
この順に見ていきます。
Google Patentsをパースする
ここではStupid Patent of the monthで紹介された特許例を使ってみます。
最初にサードパーティライブラリのHTTP.jlで特許番号US9839852のURLにアクセスできることを確認します。
using HTTP
patentURL="https://patents.google.com/patent/US9839852"
r=HTTP.request("GET", patentURL)
@show r.status
r.status = 200
次にGumbo.jlを使ってHTMLをパースします。
using Gumbo
h = parsehtml(String(r.body))
請求項だけを抜き出す
次にCSSセレクターを使って必要な部分を抽出します。 ここでは、Cascadia.jlを使います。
たとえば、titleタグの中身を表示したければ以下のようにします。
using Cascadia
s = Selector("title")
q = eachmatch(s, h.root)
q[1] |> nodeText |> println
US9839852B2 - Interactive guitar game
- Google Patents
タグに囲まれた文章ではなく、href属性を取得したければ以下のようにします。
qa = eachmatch(Selector("a"), h.root)
qa[1].attributes["href"] |> println
https://patentimages.storage.googleapis.com/ea/a3/cd/747072854dad30/US9839852.pdf
Cascadia.jlについては、ドキュメントがまだ充実していないので、気が向いたらまとめを作ってみたいと思います。 いよいよ請求項を抜き出します。
Google Patentの請求項の構造を確認する
Google Patentのソースを見てみると、請求項は"claims"というクラスのブロック要素の中に記述されていることがわかります。
独立クレームの場合は、その中の"claim"というクラスのブロック要素の中にある"claim"というクラスのブロック要素の中に記述されています。
一方で従属クレームの場合は、"claim-dependent"というクラスのブロック要素の中にある"claim"というクラスのブロック要素の中に記述されています。
クラス名が重複しているので、自分でも何を書いているのかよくわかりません。 図示してみるとわかりやすいです。
独立請求項だけを抜き出したいときは、Selector(".claims .claim .claim")
とすればOKです。 実際に最初の請求項を抽出します。
using Cascadia
s_claim = Selector(".claims .claim .claim")
q_claim = eachmatch(s_claim, h.root)
claim1 = q_claim[1] |> nodeText
@show claim1
BoundsError: attempt to access 0-element Vector{Gumbo.HTMLNode} at index [1]
(2021/5/1追記) すべての特許にこの構造が当てはまるわけではないようです。
全請求項を抜き出したいときは、claimクラスのdivのidが"CLM-"で始まることに注目して、
eachmatch(Selector("""div[id^="CLM-"]"""), h.root)
とすればOKでした。
翻訳する
親切なひとがGoogle翻訳のパッケージを作ってくれていました。
READMEをみるとわかりますが、使用例の翻訳言語が"ja"になっていて、いかにも英語の苦手な日本人におあつらえ向きのパッケージです。 せっかくなので☆を差し上げておきました。試しに何か訳させてみましょう。
using GoogleTrans
GoogleTrans.translate("おれは人間をやめるぞ!ジョジョーッ!","en") |> println
Expected end of input
Line: 0
Around: ...8865",2]]]...
^
うまく翻訳できたでしょうか?
Google翻訳は優秀なのですが、図.をイチジクと訳すのは、本当にやめてほしいと思います。
GoogleTrans.translate("Fig. 1 ","ja") |> println
Expected end of input
Line: 0
Around: ...8999",2]]]...
^
Pluto.jlでWebアプリ化
Pluto.jlはこちらで紹介したように、HTMLインプットを使って簡単にウェブアプリっぽいものを作ることができます。
これまで紹介した機能をPluto.jlでまとめて、特許翻訳アプリっぽいものを作ってみました。[3]
見た目は下のiframeで表示した通りです。そのままでは動きませんが、右上にあるEdit or run this notebook を押すとクラウド上で動かすことが可能です。binderの仕様上、立ち上がりにはちょっと時間がかかります。 (Pluto.jlが使える人は自分のPCで動かすこともできます。)
ただ翻訳するだけではつまらないので、特許のpdfのダウンロードリンク、特許に関するメモを自分で書いてダウンロードできる機能を追加しました。
[3] | MITのComputationalthinkingの授業のPlutoノートブックを参考にしています。 |
Pluto.jlでhtmlを生成する
このノートブックでは、請求項の原文と翻訳を表形式で並べて表示しました。 その際には、htmlをjuliaに書かせる必要があって、少々躓きました。[4]
結果的には、PlutoUI.jlの HTML関数にdo構文を使ってテキストをぶち込むことで解決できたので、紹介しておきます。
using PlutoUI
@doc(HTML) |> println
`HTML(s)`: Create an object that renders `s` as html.
```
HTML("<div>foo</div>")
```
You can also use a stream for large amounts of data:
```
HTML() do io
println(io, "<div>foo</div>")
end
```
!!! warning
`HTML` is currently exported to maintain backwards compatibility, but this export is deprecated. It is recommended to use this type as `Docs.HTML` or to explicitly import it from `Docs`.
do構文を使った例は、iframeの請求項の下で確認できます。
[4] | md"a=$(a)" はできてもhtml"a=$(a)" はできないし、md"text1"*md"text2" もできない。ただし、HypertextLiteral.jlを使うと@htl"$(a)" ができるらしい。 |
まとめ
Google Patentsのページをパースする方法を紹介した。(HTTP.jl Gumbo.jl Cascadia.jl)
Google翻訳をjuliaで実行する方法を紹介した。(GoogleTrans.jl)
Plutoノートブック形式で翻訳アプリとしてまとめてみた。(Pluto.jl PlutoUI.jl)
今回は特許を翻訳するという事例での紹介ですが、要素技術は色々つぶしが効くと思います。誰かの参考になれば幸いです。
めでたしめでたし