nyanpyou Note

主な目的は調べたり作ったりしたプログラミング備忘録(予定)

Pythonで論文の情報をスクレイピングする

きっかけ

論文投稿雑誌の一部にはVideo Abstractなるものを一緒に乗せることが可能らしい。
初めて聞いたものなので、一体どんなものなのか他の人達の投稿を確認しようと思ったが、どうやら目次を見てもその論文にVideo Abstractが載っているのかの記載は無く、いちいち該当ページを開いて確認しないとわからない。
あまりにも面倒で手間がかかるので、以前書籍等で読んだPythonを用いたスクレイピングを試してみることにした。
…のだが該当サイトのrobots.txtをよく読んでみると、特定のクローラー以外のアクセスを禁止している事が発覚した。
アクセス毎に数秒待ち、アクセス件数も50にさえ満たないのでサーバーに負荷をかけるようなことは無いと思うが、禁止されている以上従うしかないので、以下は次回別の場所で使うためのメモ書きということにする。

目的

目次のページからどの論文にVideo Abstractが掲載されているかを調べ、該当論文のURLを取得する。

コード

import requests
from bs4 import BeautifulSoup
from urllib.parse import urlparse
import time
import random

target_url = input("URL?")
# アクセスの待ち時間(負荷軽減&bot判定回避)1~5秒の間でランダムに待つ
sleeptime = random.uniform(1, 5)

domain = '{uri.scheme}://{uri.netloc}'.format(uri=urlparse(target_url))

# Firefoxからアクセスしているように偽装
# 偽装しないとbotとみなされてCaptchaページに飛ばされる事がある
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0"

# 論文ページへのリンクのリストを取得する

links = []
response = requests.get(target_url, headers={"User-Agent":user_agent})
soup = BeautifulSoup(response.content, "html.parser")
article_title = soup.find_all("a", attrs={"class":"art-list-item-title"})

for i in article_title:
    # iはbs4.element.Tagオブジェクト
    link = i.get("href")
    # hrefタグにドメインを省略してリンクが書かれているので、
    # ドメインをくっつける
    links.append(domain+link)
if len(links) == 0:
    print("Article's link is not found.")
else:
    print("Success")

time.sleep(sleeptime)

# 対象のページにVideo abstractが存在するか調べる
# 存在したらそのページのURLをリストに保存

articles_with_VideoAbstract = []
for url in links:
    response = requests.get(url, headers={"User-Agent":user_agent})
    soup = BeautifulSoup(response.content, "html.parser")
    video_abstract = soup.find_all("div", attrs={"class":"videoPlayer mb-1"})
    if len(video_abstract) == 0:
        pass
    else:
        articles_with_VideoAbstract.append(url)
    time.sleep(sleeptime)

if len(articles_with_VideoAbstract) == 0:
    print("Articles with VideoAbstract is not found.")    
else:
    print("Articles with VideoAbstract")
    for i in articles_with_VideoAbstract:
        print(i)
  • スクレイピングを始める前に、robots.txtにアクセスしてスクレイピングする際の規則をチェックする。
    ディレクトリの最上位に置く決まりになっているようなので、ドメイン/robots.txtとアドレスバーに打ち込んで中身を確認する。
    一番下の方に一般のクローリングについて書かれていることもあるのでしっかり見落とさずに確認すること!(自戒)

  • user_agentは自分の使っているブラウザのものを確認するといいと思うが、各種ブラウザについてまとめてくれている人もいるのでこちらも参考にすると便利かもしれない。 qiita.com

  • urlparse()にURLを渡すと以下の返り値が得られる。

ParseResult(scheme='https', netloc='iopscience.iop.org', path='/issue/0031-9120/55/5', params='', query='', fragment='')
  • 以下はrobots.txtをしっかり読まないままテストしていた時の覚書だが、何度も言うように事前にきっちり理解してから作業しましょう()
    今回はドメインを省略したURLがタグに記載されていたので、事前にこれを利用してドメインを抜き出しておき、結合することにした。
    webサイトへのアクセスを短時間に連発すると、botと判定されてCaptchaページに飛ばされてしまう。実際に待ち時間を0.5秒に設定してみたらbot判定を食らってreCaptcha認証ページ(私はロボットではありません。にチェックを付けるあれ)に飛ばされた。一度このページに飛ばされると手動でブラウザからページにアクセスして認証しないと接続できなくなるので気を付ける。
    このサイトはどうも同じ時間間隔でアクセスし続けてもbot判定を食らうようだったので、こちらの回避のためにアクセス時間も乱数で散らすようにしてみた。

まとめ

欲しい情報を自動で拾ってくるスクレイピングプログラムを作ってみた。やはり知識だけあっても自分で独自に作ってみないと身につかない。今回は作ったものの使えずに終わってしまったが、次回以降はしっかりと運用したい。

参考にしたサイト

URLからドメインを抜き出す方法
http://blog.mwsoft.jp/article/176458287.html

qiita.com