お久しぶりです,ぴのです.新年度が始まってから講義やら研究やらで忙しくなってきました.講義はオンラインで開講されるものがほとんどですが,研究室で受ける方が捗るし学食でメシを食えるので毎日足を運んでいます.
さて,久しぶりに講義を受けるとたまに登場するのが「Bo○kQ(旧:Bo○kRoll)」です.知らない人のために説明すると,大学などで講義スライドなどを閲覧することのできるwebビューアのことです.Bo○kQ自体はメモ機能や栞機能などがあって便利といえば便利なのですが(使ったことないけど),このビューアには「スライドをダウンロードできない」という学生にとって致命的な欠陥があります.なぜそんな欠陥があるかというと,「教材をダウンロードできない」という機能がBo○kQの目的の一つだからです(参考).
今回はそんなBo○kQからPDFを頂戴するプログラムを書いてみました.ちなみに水色の研究MoodleのBo○kRollは仕組みが全く違っているようでうまくいきません.
注意
そもそもBo○kQは「教材をダウンロードできない」ことが目的の一つであるアプリなのでそこから直接PDFを頂戴するという行為を行うのは一考の余地があります(参考).また,著作権法上の問題からもわりとグレーゾーンなので頂戴したPDFの取扱いには注意しましょう.何かあっても管理人は責任はとれないぞ.
実行環境
Python3で動作します.
事前準備
必要なライブラリは以下のコマンドでインストールできます.
pip install requests bs4 img2pdf tqdm
また,実行前に以下のようなsecrets.jsonファイルを作成して,bookq2pdf.pyと同じ階層に作成しておく必要があります.”id”にはSSO-KIDを,”passwd”にはパスワードを記述してください.
{
"id":"0000000000",
"passwd":"XXXXXXXXXXX"
}
ファイル構造はこんな感じ.
- bookq
- main.py
- bookq2pdf.py
- secrets.json
- (output.pdf)
プログラム全体
import bookq2pdf
bookq = bookq2pdf.Bookq()
bookq.login()
bookq.get_pdf(book_url='https://bookq.s.kyushu-u.ac.jp/book/view?contents=...', page_num=10)
import re
import time
import json
from tqdm import tqdm
import requests
from bs4 import BeautifulSoup
import img2pdf
class Bookq():
URL = 'https://bookq.s.kyushu-u.ac.jp'
def __init__(self):
self._session = None
self._imgs = []
def login(self, secrets_file='secrets.json'):
with open(secrets_file, 'r') as f:
secrets = json.load(f)
self._session = requests.session()
login = self._session.get(f'{Bookq.URL}/login')
soup = BeautifulSoup(login.text, 'html.parser')
csrf = soup.select_one('input[name=_csrf]').get('value')
login = self._session.post(f'{Bookq.URL}/login', data={'userid': secrets['id'], 'password': secrets['passwd'],'_csrf': csrf})
def _bookq2jpg(self, book_id, page_num, sleep_time):
for page in tqdm(range(1, page_num+1)):
r = self._session.get(f'{Bookq.URL}/contents/unzipped/{book_id}_2/OPS/images/out_{page}.jpg', stream=True)
if r.status_code == 200:
self._imgs.append(r.content)
time.sleep(sleep_time)
else:
break
return
def _jpg2pdf(self, file_name):
with open(file_name,'wb') as f:
f.write(img2pdf.convert(self._imgs))
self._imgs.clear()
def get_pdf(self, book_url, page_num, file_name='output.pdf', sleep_time=1):
book_id = re.findall(r'contents=.+', book_url)[0].replace('contents=', '')
try:
self._bookq2jpg(book_id, page_num, sleep_time=sleep_time)
self._jpg2pdf(file_name)
except Exception as e:
print(f'\n{e}')
else:
print(f'\n\"{file_name}\" is generated.')
使い方
- main.py内の関数に適切な引数を設定する.
Bookqインスタンスの持つメソッドの詳細については次の項を参照してください. - python3 main.pyを実行する.
メソッド
login()
login(
secrets_file='secrets.json'
)
BookQへログインを行うメソッド.
Args | |
---|---|
secrets_file | IDとパスワードを保存しているJSONファイルへのパス |
get_pdf()
get_pdf(
book_url, page_num, file_name='output.pdf', sleep_time=1
)
スライドをPDF形式で取得するメソッド.
Args | |
---|---|
book_url | スライドが表示されているビューワーのURL |
page_num | 取得するスライドの枚数を指定(システムエラー回避のため) |
file_name | 出力するPDFの名前 |
sleep_time | スライド取得毎に入るスリープの間隔(デフォルトは1秒) |
おわりに
管理人のゴールデンウィークは全くゴールデンじゃないらしいぞ
コメント