automagicaことはじめ
automagicaとは
automagica
を利用すると、最近流行のRPA(Robotics Process Automation)をpythonで実施することができる。
Autohotkey
も類似のツールだが、こちらは独自のスクリプト言語でwindowsに特化した命令を多数持っており歴史も長い。日本語の情報も充実している。
そのような状況の中でautomagica
を利用する利点は、以下のようなものが挙げられるだろう。
- windows操作に限定しない様々な自動化処理関数を持っている。というのも、
automagica
自体は他のオープンソースのライブラリを統一的にかつ簡単に利用できるようなラッパー関数を提供しているもの。 - pythonで書ける。
-
Autohotkey
は単にwindows操作のスクリプト化しかできないが、automagica
はwebページをhtml構文解析を行い、タグなどから必要な情報を取得する、といったことができる。(実際は基盤になっているSelenium
の機能だが) - マウス、キーボードの操作、エクセルの操作なども可能でこれらをシームレスに扱える。
今回は、上述のweb解析機能を使って、webページから必要な情報を取得してそれをエクセルにコピーする、という機能を実現する。
実現すること
- 論文検索ページで任意の検索ワードを設定し検索する
- 検索結果の任意の要素(ここでは論文名、文献、著者名、ページ数)を取得
- 取得した情報をエクセルファイルとして保存
automagicaのインストール
automagica
はpip
では最新版が入れられないようだ。githubからpip
で入れるためには以下のようにする。
pip install git+https://github.com/OakwoodAI/automagica/
from automagica import *
のようにして使おう。
ブラウザをコントロールする
excelファイルとブラウザの立ち上げ
automagica
では先述の通りHTML構造から任意の要素を取得する、という使い方ができるが、まず以下のようにしてブラウザを動かす。
target_URL
は論文検索システムCiniiを今回は指定する。
# excel open
excel_path = this_excel_path
ExcelCreateWorkbook(path=excel_path)
# Open Chrome
browser = ChromeBrowser()
# Browse target URL
target_URL = 'https://ci.nii.ac.jp'
browser.get(target_URL)
automagica
がベースにしているselenium
は、操作するブラウザーとしてgooglechrome、firefoxまたはedgeを用いることができる。
chromebrowserというのがvivaldiとかも対象にしているのかは分からない。
ともかく作成したインスタンス(ここではbrowser
)にHTMLの構造が取得されるので、これに操作していく。
excelの操作はExcelCreateWorkbook
でまずworkbookを作成する。
検索ワードを入力して実行する
以下のようなコードを実行する。
## Enter Search Text
search_word = "hoge"
browser.find_element_by_name('q').send_keys(search_word)
## search実行ボタンの取得
exec_search = browser.find_element_by_xpath('//*[@id="article_form"]/div/div[1]/div[2]/div[2]/button')
## searchボタンを押す
exec_search.click()
find_element_by_name
はタグのname
で指定されている要素名で探す。
この場合は、検索ワードの入力部分が、<input name="q">
となっている。名前がqだということだ。
このように該当ページの取得したいHTMLの要素がどのように一意に特定できるのかは、試行錯誤する必要がある。
検索ワード部分を指定したらそこにテキスト入力するメソッドが、send_keys()
になるので、引数に検索ワードを入れる。
検索ワードが入力できたら検索実行ボタンを押す。ここではfind_element_by_xpath
で指定している。
Xpathはこちらによると、
XPathはXML文章中の要素、属性値などを指定するための言語です。
XPathではXML文章をツリーとして捉えることで、要素や属性の位置を指定することができます。
HTMLもXMLの一種とみなすことができるため、XPathを使ってHTML文章中の要素を指定することができます。
ということ。イメージとしてはファイルをドライブルートから絶対パスで要素を指定するのと同じような形で、
ある要素のHTMLの中での場所を指定するような形、かと思う。
これはchromeであれば右クリック→検証を行うと、取得したい要素のHTML上の表記がわかるので、
その上で右クリックしてCopy->Copy XPath
で取得できるので、それを引数に入れる。
便利だけど、ファイルの絶対パス指定と同じで少しでも構造が変わってしまうと指定できなくなる柔軟性の低さもある。
この辺りは使いわけていく必要あり。
指定できたら、そのオブジェクトのclick()
メソッドでボタンを押すのと同様の効果が得られる。
ページ結果の取得
1ページには複数件の文献検索結果が表示される。各文献毎に内容を取得して文献数だけループする。
find_elements_by_class_name
は引数の名前のクラス名を持つ全要素のリストを取得する。
ここではリストの各要素でループを実行することで、各論文のコンテンツにアクセスしている。
find_element_by_class_name
は全要素ではなく単一の要素を返す。一番最初にヒットしたもののようだ。
find_element_by
は他にもtag_name
など様々なものが使えるので、HTMLを見て使いやすいものを使用するのがいいと思う。
excelに対する結果の書き込みはExcelWriteRowCol
で行う。開いたexcelファイルのパス、かきこむ場所の行数、列数、書き込む内容、となっている。
# 各論文のコンテンツを示すelementを1ページ内の塊、elementsを取得
this_articles = browser.find_elements_by_class_name('paper_class')
# elements内の各要素elementでループ
for this_article in this_articles:
# 通し番号を増加
total_index += 1
# タイトルの取得
this_link = this_article.find_element_by_tag_name('a')
this_title = this_link.text
link_text = this_link.get_attribute("href")
# 著者の取得
this_authors = this_article.text.split("\n")[1]
# ジャーナルデータの取得
this_journal_data = this_article.find_element_by_class_name('journal_title').text
# 結果の保存
# print(total_index,"\n", this_title,"\n", this_authors,"\n",link_text,"\n", this_journal_data)
# excelファイルに書き込み
ExcelWriteRowCol(excel_path, r=total_index, c=1, write_value=total_index)
ExcelWriteRowCol(excel_path, r=total_index, c=2, write_value=this_title)
ExcelWriteRowCol(excel_path, r=total_index, c=3, write_value=this_authors)
ExcelWriteRowCol(excel_path, r=total_index, c=4, write_value=link_text)
ExcelWriteRowCol(excel_path, r=total_index, c=5, write_value=this_journal_data)
## 最終ページでなければ「次へを押す」、最終ページならば終りにする
if this_page != count_next_button:
browser.find_element_by_xpath('//*[@class="paging_next btn pagingbtn"]').click()
this_page += 1
else:
print("正常に終了しました")
break
まとめ
automagica
は操作自動化に関する様々なモジュールを統一的に扱うということでとっつきやすくはあるが、まだ開発途上なのかドキュメントにも命令に対する説明が不足しているところがあって使いにくいところもある。
なので現段階ではautomagica
で例えば上記で取り上げたwebスクレイピングをとりあえずやってみて、本格的に実施する時はSelenium
を使用するとかするのがいいのかもしれない。僕もautomagica
のおかげで、pythonで実施できる自動化モジュールのことを知ることができた、という側面はあるけど、automagica
にこだわる必要はあるのかな?と思っているところだ。
もしかしたらAutomagica
は、必要最小限の機能を簡単に使ってもらう、というところに開発の主眼があるのかもしれない。
今後はautomagica
で使用しているモジュール群に関心を向けて、自動化へのとりくみを行っていきたい。
以下にコードの全文を載せておくので、参考になれば幸いです。
論文検索とエクセル取得コードの全文
# -*- coding:utf-8 -*
from automagica import *
def cinii_auto_search(this_excel_path, this_search_word):
''' 保存するexcelのパス・名前と検索語を入力して
automagicaによる自動検索、保存を行う'''
def get_loop_number(browser)->int:
'''検索ヒット数と位置ページ表示数から「次へ」を押す回数を設定'''
# search wordでの検索件数の取得
this_header = browser.find_element_by_class_name('heading')
# 取得できたelementからヒット件数と一ページあたりの表示数を抽出する
## 空白で区切られているのでリスト取得
this_text = this_header.text.split()
## 総件数は2つ目、一回の表示数は3つ目の後半
hit_num_list_index = 1
search_hit_num = int(this_text[hit_num_list_index][:-2]) # 末尾の「件中」を除いている
page_view_num_index = 2
page_view_num = int(this_text[page_view_num_index].split("-")[1])
# 「次へ」を押下する回数は、既に1ページ目が表示されているので、
# 総ページ数 // 一ページ件数 で求まる商となる
count_next_button = search_hit_num // page_view_num
return count_next_button
# excel open
excel_path = this_excel_path
ExcelCreateWorkbook(path=excel_path)
# Open Chrome
browser = ChromeBrowser()
# Browse target URL
target_URL = 'https://ci.nii.ac.jp'
browser.get(target_URL)
# phase 1 : enter search word
## Enter Search Text
search_word = this_search_word
browser.find_element_by_name('q').send_keys(search_word)
## search実行ボタンの取得
exec_search = browser.find_element_by_xpath('//*[@id="article_form"]/div/div[1]/div[2]/div[2]/button')
## searchボタンを押す
exec_search.click()
# phase 2 : ページループの取得
count_next_button = get_loop_number(browser)
# 変数設定
this_page = 0 # 表示ページ。0始まり
total_index = 0 # 検索articleの通し番号。表示は1始まり
# phase 3 : 1ページの結果の取得、ループ
while this_page <= count_next_button:
#for i in range(0,2):
# 各論文のコンテンツを示すelementを1ページ内の塊、elementsを取得
this_articles = browser.find_elements_by_class_name('paper_class')
# elements内の各要素elementでループ
for this_article in this_articles:
# 通し番号を増加
total_index += 1
# タイトルの取得
this_link = this_article.find_element_by_tag_name('a')
this_title = this_link.text
link_text = this_link.get_attribute("href")
# 著者の取得
this_authors = this_article.text.split("\n")[1]
# ジャーナルデータの取得
this_journal_data = this_article.find_element_by_class_name('journal_title').text
# 結果の保存
# print(total_index,"\n", this_title,"\n", this_authors,"\n",link_text,"\n", this_journal_data)
ExcelWriteRowCol(excel_path, r=total_index, c=1, write_value=total_index)
ExcelWriteRowCol(excel_path, r=total_index, c=2, write_value=this_title)
ExcelWriteRowCol(excel_path, r=total_index, c=3, write_value=this_authors)
ExcelWriteRowCol(excel_path, r=total_index, c=4, write_value=link_text)
ExcelWriteRowCol(excel_path, r=total_index, c=5, write_value=this_journal_data)
## 最終ページでなければ「次へを押す」、最終ページならば終りにする
if this_page != count_next_button:
browser.find_element_by_xpath('//*[@class="paging_next btn pagingbtn"]').click()
this_page += 1
else:
print("正常に終了しました")
break