LoginSignup
3
2

More than 5 years have passed since last update.

ICLR2019 OpenReview ページから論文一覧を取得する

Last updated at Posted at 2018-10-06

目的

  • ICLR2019 OpenReview に上がってる論文の一覧情報を取得し,表形式で管理をしたい

結果

  • 全論文情報を含む html を取得し,取得した html から論文の下記情報を取得した.(本記事は htmlの取得まで)
    • title
    • date
    • keyword
    • abstract
    • tldr

課題

ページのhtmlを beautiful soup を用いてスクレイピングすればよいが,下記課題が存在

  • ICRL2019 OpenReview ページは動的コンテンツになっておりスクロールしないとコンテンツが表示されない
  • ボタンをクリックしないと abstract が表示されない

-> Selenium を用いてchrome を操作し,全てのコンテンツが表示された状態のhtmlを取得すれば良い

解決手順

  1. selenium を通じてchromeを操作し,コンテンツを全て表示するまでスクロール
  2. 全て表示したら,各論文の show detailsボタンを順次クリックすることで abstractを表示させる
  3. ページのソースを取得し,beautiful soup を通じて論文の情報を取得する
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

CHROME_PATH = 'path/to/chromedriver'

def get_all_source(url):
  # 全てのソースを取得する関数
    browser = webdriver.Chrome(CHROME_PATH)
    browser.get(url)  # 指定した url をクロームで開く

    scroll_down(browser)  # 全てのコンテンツが表示されるまで下にスクロールを行う
    toggle_all(browser)  # 各論文の show details ボタンをクリックし,abstract を表示させる
    source = browser.page_source  # 全てのコンテンツ情報が表示された状態のページの html を取得
    browser.close()
    time.sleep(0.3)    

    return source

全てのコンテンツが表示されるまで下にスクロール

  • コンテンツは有限なので,全てのコンテンツが表示されるまで下にスクロールを続ける
def scroll_down(browser):
    prev_source = None
    for i in range(0, 1000):
        if i == 0:
            time.sleep(1)

        browser.execute_script('window.scrollBy(0,2000)', '')  # ページを下へスクロール
        scroll_count += 1
        time.sleep(0.3)
        print ('Scroll: {}'.format(scroll_count))

        if scroll_count % 10 ==0:
            if browser.page_source == prev_source:  # スクロールしてもページの情報が変わらなければ終了
                break
            prev_source = browser.page_source
    return

各論文の Show details ボタンをクリックして abstract を表示させる

  • クリックをさせる際には,クリック対象が画面に表示されていなければならない
    • 表示されていない状態でクリックさせようとすると element is not visible エラー
    • クリック対象の位置まで画面遷移 & is_displayed() メソッドで表示されていることを確認して対処
  • is_displayed()==True でもクリックできない場合が存在
def wait_for_element(element):
    # クリック対象が画面に表示されているか確認,表示されていなければしばらく待つ関数
    if element.is_displayed():
            print(element.is_displayed())
            return
    else:
            time.sleep(.1)
            return wait_for_element(element)

def toggle_all(browser):
  # 全てのShow details ボタンをクリックし,abstract を表示させる関数
  
  # ページ最上部へ移動
    browser.find_element_by_tag_name('body').send_keys(Keys.CONTROL + Keys.HOME)
    time.sleep(3)

  # 全ての Show details ボタンを取得 (note-contents-toggle 属性を持つオブジェクトが show details ボタンに対応することは 別途ソースから確認)
    buttons = browser.find_elements_by_class_name('note-contents-toggle')

  # 全てのボタンをクリック
    for button in buttons:
    # ボタンの位置まで画面を移動させる
        webdriver.ActionChains(browser).move_to_element(button).perform()
    
    # ボタンが画面に表示されていることを確認
        wait_for_element(button)
        print('---------------------')
        time.sleep(0.2)

    # ボタンをクリック
        button.click()

def toggle_all(browser):
  # 全てのShow details ボタンをクリックし,abstract を表示させる関数
  
  # ページ最上部へ移動
    browser.find_element_by_tag_name('body').send_keys(Keys.CONTROL + Keys.HOME)
    time.sleep(3)

  # 全ての Show details ボタンを取得 (note-contents-toggle 属性を持つオブジェクトが show details ボタンに対応することは 別途ソースから確認)
    buttons = browser.find_elements_by_class_name('note-contents-toggle')

  # 全てのボタンをクリック    
for i, button in enumerate(buttons):
    # ボタンの位置まで画面を移動させる
        webdriver.ActionChains(browser).move_to_element(button).perform()
    
    # ボタンが画面に表示されていることを確認
        wait_for_element(button)
        print(f'toggle {i}')
        time.sleep(0.2)

        # ボタンをクリック
        button.click()

    return 

ソースまとめ

上記のコードまとめたソース

import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

CHROME_PATH = 'path/to/chromedriver'

def wait_for_element(element):
    if element.is_displayed():
            print(element.is_displayed())
            return
    else:
            time.sleep(.1)
            return wait_for_element(element)

def toggle_all(browser):
    browser.find_element_by_tag_name('body').send_keys(Keys.CONTROL + Keys.HOME)
    time.sleep(3)
    buttons = browser.find_elements_by_class_name('note-contents-toggle')
    for i, button in enumerate(buttons):
        webdriver.ActionChains(browser).move_to_element(button).perform()
        wait_for_element(button)
        print(f'toggle {i}')
        time.sleep(0.1)
        button.click()

    return 

def scroll_down(browser):
    prev_source = None
    for i in range(0, 1000):
        if i == 0:
            time.sleep(1)

        browser.execute_script('window.scrollBy(0,2000)', '')
        time.sleep(0.3)
        print (f'Scroll: {i}')

        if i % 10 ==0:
            if browser.page_source == prev_source:
                break
            prev_source = browser.page_source
    return 

def get_all_source(url):
    browser = webdriver.Chrome(CHROME_PATH)
    browser.get(url)

    scroll_down(browser)
    toggle_all(browser)
    source = browser.page_source
    browser.close()
    time.sleep(0.3)    

    return source

参考

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2