LoginSignup
4
5

More than 3 years have passed since last update.

【Selenium】「次ページ」への繰返し移動は、while文を使う

Last updated at Posted at 2020-11-07

Tips

1. While文によるページ遷移の繰り返し処理(うまくいく)

selenium_success.py
# 1ページ目の次のページ(2ページ目)のURLを取得
next_page_url = driver.find_element_by_class_name("js-next-page-link").get_attribute("href")

# 2ページ目から最終ページまでをループ処理する
while len(next_page_url) > 0:
    driver.get(next_page_url)
    #要素がロードされるまでの待ち時間を10秒に設定
    driver.implicitly_wait(10)
    next_page_html = driver.page_source.encode('utf-8')

# 任意の処理の実装コードをここに書く

    next_page_url = driver.find_element_by_class_name("js-next-page-link").get_attribute("href")
else:
    print("\n\n最後のページの処理が終わりました。\n\n")

2.for文によるページ遷移の繰り返し処理(途中で止まる)

selenium_failure.py
# 1ページ目の次のページ(2ページ目)のURLを取得
next_page_url = driver.find_element_by_class_name("js-next-page-link").get_attribute("href")

# 2ページ目から最終ページまでをループ処理する
if len(next_page_url) != 0:
    driver.get(next_page_url)
    #要素がロードされるまでの待ち時間を10秒に設定
    driver.implicitly_wait(10)
    next_page_html = driver.page_source.encode('utf-8')

# 任意の処理の実装コードをここに書く

    next_page_url = driver.find_element_by_class_name("js-next-page-link").get_attribute("href")
else:
    print("\n\n記事検索結果の最後のページの処理が終わりました。\n\n")

実際に作成したコード

selenium_python_multi_pages_while.py
# coding: utf-8
import time, argparse, datetime
from selenium import webdriver
from bs4 import BeautifulSoup
from pprint import pprint
import pandas as pd
import numpy as np
import time

### 定数 ###
url = "http://qiita.com"

### 変数の初期化宣言 ###
pagenum = 0
# コマンドライン引数を受け取る
parser = argparse.ArgumentParser()

# コマンドライン引数を1つだけ受け取る
parser.add_argument('-word', '--search_word', default='Python', help='Qiitaの記事検索ページに入力する検索単語を指定してください。')
parser.add_argument('-max', '--max_page_num', default='50', help='該当するページが複数ある場合、データ取得するページ数に上限を設定する場合は、上限ページ数を指定してください。')
args = parser.parse_args()
search_word = args.search_word
num_of_search_pages = int(args.max_page_num)

print("\n\n入力された検索文字列:      ", args.search_word, "\n")
print("記事一覧ページが複数ページに及ぶ場合、{}ページまでで処理を打ち切ります。".format(num_of_search_pages))

# outputファイル名
output_file_name = str(datetime.datetime.now()) + "_Search: " + search_word

### メソッド定義 ###
def proceed_each_page(page_num, this_page_html, driver):
    from bs4 import BeautifulSoup
    this_soup = BeautifulSoup(this_page_html, 'lxml')
    print("""
    ================================
           {}ページ目を処理中...    
    ===============================
    """.format(page_num))
    results = this_soup.find_all("h1", class_="searchResult_itemTitle")
    # 結果を記事タイトルリストに格納
    this_page_title_list = []
    for result in results:
        title_texts = result.findAll("a")
        title_texts = str(title_texts[0]).replace("<em>", "").replace("</em>", "").split(">")[1:]
        title_texts = title_texts[0]
        pos = title_texts.find('</a')
        title_text = title_texts[:pos]
        this_page_title_list.append(title_text)

    console_message = "検索結果画面の{}ページ目の記事件数:  ".format(pagenum) + str(len(this_page_title_list)) + "\n\n"
    pprint(this_page_title_list)

    # 結果をURLリストに格納
    this_page_url_list = []
    for result in results:
        href = result.findAll("a")[0].get("href")
        this_page_url_list.append(str(url + href))

    # 投稿者を投稿者リストに格納
    # <div class="searchResult_header"><a href="/niiku-y">niiku-y</a>が2019/08/07に投稿</div>
    this_page_author_list = []

    results = this_soup.findAll(class_="searchResult_header")
    for result in results:
        author = result.findAll("a")[0].get("href")
        author = author.replace("/", "")
        this_page_author_list.append(author)

    # nページ目から取得した記事であることをデータ保存
    this_page_num_list = [page_num]*len(this_page_title_list)

    ## 検索結果画面のnページ目の画面スクリーンキャプチャを取得 
    # 画面の縦横サイズのデータを取得
    w = driver.execute_script("return document.body.scrollWidth;")
    h = driver.execute_script("return document.body.scrollHeight;")
    driver.set_window_size(w,h)
    # 画面スクリーンキャプチャファイル(画像ファイル)の保存場所とファイル名を指定
    FILENAME = "./{search_word}_page{number}_screen_{datetime}.png".format(search_word=search_word, number=page_num, datetime=str(datetime.datetime.now()))  
    # 画像を保存
    driver.save_screenshot(FILENAME)

    #処理したWebページの情報を格納した各listを返す
    return [this_page_num_list, this_page_author_list, this_page_title_list, this_page_url_list, driver]

### メソッド定義おわり 

### main処理
driver = webdriver.Chrome()

# Qiitaのトップページにアクセス
driver.get(url)

# 記事の検索ボックス欄に、キーワードを入力
search = driver.find_element_by_class_name("st-Header_searchInput")
search.send_keys(search_word)
search.submit()
time.sleep(5)

# 検索結果の記事一覧ページの1ページ目のHTMLを取得
first_page_html = driver.page_source.encode('utf-8')

# 1ページ目を処理
page_num = 1
all_page_num_list = []
all_page_author_list = []
all_page_title_list = []
all_page_url_list = []

this_page_num_list, this_page_author_list, this_page_title_list, this_page_url_list, driver = proceed_each_page(page_num, first_page_html, driver)

all_page_num_list = all_page_num_list + this_page_num_list
all_page_author_list = all_page_author_list + this_page_author_list
all_page_title_list = all_page_title_list + this_page_title_list
all_page_url_list = all_page_url_list + this_page_url_list

# 受け取ったdriverの指示対象のWebページに、次のページがある場合は、次のページに移動する
# next_page_urlの返り値はlist型。次のページが記載された上記のタグが存在しない場合は、空のlistが返る
next_page_url = driver.find_element_by_class_name("js-next-page-link").get_attribute("href")
print("=======")
print(type(next_page_url))
print("=======")

# 2ページ目から(最終ページ目 もしくは、{num_of_search_pages}ページ目までのいずれか小さいページ番号目)までをループ処理する
# (num_of_search_pages)ページ目を最終ページにするためには、{num_of_search_pages -1)回、次のページをめくる
while len(next_page_url) > 0 and page_num <= (num_of_search_pages - 1):
    driver.get(next_page_url)
    #要素がロードされるまでの待ち時間を10秒に設定
    driver.implicitly_wait(10)
    #time.sleep(5)
    next_page_html = driver.page_source.encode('utf-8')
    page_num += 1
    this_page_num_list, this_page_author_list, this_page_title_list, this_page_url_list, driver = proceed_each_page(page_num, next_page_html, driver)
    all_page_num_list = all_page_num_list + this_page_num_list
    all_page_author_list = all_page_author_list + this_page_author_list
    all_page_title_list = all_page_title_list + this_page_title_list
    all_page_url_list = all_page_url_list + this_page_url_list
    next_page_url = driver.find_element_by_class_name("js-next-page-link").get_attribute("href")
    print("=======")
    print(next_page_url)
    print(len(next_page_url))
    print("=======")
else:
    print("\n\n記事検索結果の最後のページの処理が終わりました。\n\n")

# Excelファイル出力
print("\n\n取得した検索結果のデータをExcelファイルに出力します。\n\m")
data = np.array([all_page_num_list, all_page_author_list, all_page_title_list, all_page_url_list]).T

index_list = list(range(len(all_page_num_list)))
column_list = ['検索結果画面内の掲載ページ番号', '投稿者', '記事のタイトル', '記事のURL']
output_df = pd.DataFrame(data, columns=column_list, index=index_list)
pprint(output_df)

# 結果をExcelファイルに出力
output_df.to_excel('./'+output_file_name + '.xlsx', sheet_name='Qiita_Articles_list')

# Webページに自動アクセスするために生成したdriverインスタンスを閉じて消去(メモリ開放)する
time.sleep(5)
driver.close()
driver.quit()

( 使い方 )

Console
$ python  selenium_python_multi_pages_while.py --help
usage: selenium_python_multi_pages_while.py [-h] [-word SEARCH_WORD]
                                            [-max MAX_PAGE_NUM]

optional arguments:
  -h, --help            show this help message and exit
  -word SEARCH_WORD, --search_word SEARCH_WORD
                        Qiitaの記事検索ページに入力する検索単語を指定してください。
  -max MAX_PAGE_NUM, --max_page_num MAX_PAGE_NUM
                        該当するページが複数ある場合、データ取得するページ数に上限を設定する場合は、上限ページ数を指定してください。
$ 

( 実行例とその結果 )

Console
$ python  selenium_python_multi_pages_while.py -word Haskell -max 5


入力された検索文字列:       Haskell

記事一覧ページが複数ページに及ぶ場合、5ページまでで処理を打ち切ります。

    ================================
           1ページ目を処理中...
    ===============================

['HaskellでMD5 #Haskell',
 'stylish-haskellをHexFloatLiteralsやNumericUnderscoresに対応させる',
 'Haskell チュートリアル (Haskell Day 2016)',
 'VSCodeのHaskell拡張を使って最速開発環境構築',
 'stylish-haskellをBlockArgumentsに対応させる',
 'Haskell で Functor を使う',
 'Windows10 HomeでDocker + VSCodeによるhaskellの環境構築',
 'Docker + Haskell の Hello Worldビルド',
 'Haskellの型クラスで遊ぶ',
 'HaskellのEitherについて']
=======
<class 'str'>
=======

    ================================
           2ページ目を処理中...
    ===============================

['Haskellの関数の型とかカリー化とか #Haskell',
 'Haskell と SQLite',
 'Haskell 入門',
 'Haskell/GHC 記号の意味を検索するためのリファレンス集',
 'Approaching Haskell',
 'Haskell入門記事備忘録',
 'Typing Haskell in Haskellを読んでみる',
 '[Haskell] Some memo about learning haskell',
 'Haskell入門 - Stackのインストールと設定',
 'Ruby内にHaskellのコード埋め込むHaskellというGem作ったヨ!']
=======
https://qiita.com/search?page=3&q=Haskell
41
=======

    ================================
           3ページ目を処理中...
    ===============================

['Typing Haskell in Haskellを読んでみる',
 'VisualStudioCodeでHaskell開発環境を整える',
 'なぜHaskellを学ぶと良いか',
 '[Haskell] Some memo about learning haskell',
 'Haskell インストールメモ',
 "VSCodeでCouldn't start client Haskell IDEが出る(Windows 10)",
 'Stackをhaskell-modeで使ってみよう',
 'Haskellのお勉強その1-Haskell環境構築',
 'HaskellerがRustに入門してみた',
 'Haskellの入門から中級者になるまでの指針']
=======
https://qiita.com/search?page=4&q=Haskell
41
=======

    ================================
           4ページ目を処理中...
    ===============================

['Atom EditorでHaskell',
 'Haskellで逆ポーランド記法の計算機を作る',
 'Atomエディタでide-haskellを使うまでの手順',
 'MacでHaskellを触ってみるメモ 0.1',
 'Haskellを始めてみた',
 'ATOMのide-haskell導入手順(MacOS X)',
 '【翻訳】PureScriptとHaskellの違い\u3000+α',
 'Haskellメモ',
 'Windows10でHaskell開発環境構築',
 'Haskellで食べていけるよ!!']
=======
https://qiita.com/search?page=5&q=Haskell
41
=======

    ================================
           5ページ目を処理中...
    ===============================

['Haskell Weekly News 日本語版(お試し) (5/8)',
 '世界のHaskell専門家に向けたメッセージ全文',
 'JSON から各言語のコードを生成する quicktype の Haskell 出力を実装した',
 'haskell-ide-engine導入',
 'macOSでVS CodeのHaskellの環境構築で嵌った点',
 'Go製のToolをHaskellで実装する',
 'Haskellの($)と(.)の違い',
 'Samuel Gélineau からの返信その1(翻訳)',
 'Haskell 環境構築 メモ',
 'Haskellerの1週間Rust入門チャレンジ Day 1 #Rust']
=======
https://qiita.com/search?page=6&q=Haskell
41
=======


記事検索結果の最後のページの処理が終わりました。




取得した検索結果のデータをExcelファイルに出力します。
\m
   検索結果画面内の掲載ページ番号                投稿者  \
0                1          Tatsuki-I
1                1          mod_poppo
2                1           hiratara
3                1             sgmryk
4                1      sparklingbaby
5                1         oskats1987
6                1     atsuyoshi-muta
7                1             dd0125
8                1         oskats1987
9                1             Izawa_
10               2          Tatsuki-I
11               2        satosystems
12               2            a163236
13               2        takenobu-hs
14               2         pumbaacave
15               2               F_cy
16               2              nka0i
17               2          zhupeijun
18               2      sparklingbaby
19               2         gogotanaka
20               3              nka0i
21               3          legokichi
22               3              arowM
23               3          zhupeijun
24               3             tnoda_
25               3            yutasth
26               3        t-mochizuki
27               3       CPyRbJvCHlCs
28               3            kanimum
29               3           Lugendre
30               4              eielh
31               4       inatatsu_csg
32               4       busyoumono99
33               4       hiroyuki_hon
34               4              Cj-bc
35               4  nakamurau1@github
36               4         hiruberuto
37               4             sahara
38               4       kitsukitsuki
39               4         reotasosan
40               5          imokurity
41               5         reotasosan
42               5              algas
43               5         dyoshikawa
44               5                dsm
45               5        kwhrstr1206
46               5         TTsurutani
47               5         reotasosan
48               5              1ain2
49               5          Tatsuki-I

                                              記事のタイトル  \
0                                HaskellでMD5 #Haskell
1   stylish-haskellをHexFloatLiteralsやNumericUnders...
2                  Haskell チュートリアル (Haskell Day 2016)
3                        VSCodeのHaskell拡張を使って最速開発環境構築
4                stylish-haskellをBlockArgumentsに対応させる
5                               Haskell で Functor を使う
6       Windows10 HomeでDocker + VSCodeによるhaskellの環境構築
7                   Docker + Haskell の Hello Worldビルド
8                                     Haskellの型クラスで遊ぶ
9                                  HaskellのEitherについて
10                      Haskellの関数の型とかカリー化とか #Haskell
11                                   Haskell と SQLite
12                                         Haskell 入門
13                   Haskell/GHC 記号の意味を検索するためのリファレンス集
14                                Approaching Haskell
15                                     Haskell入門記事備忘録
16                    Typing Haskell in Haskellを読んでみる
17         [Haskell] Some memo about learning haskell
18                        Haskell入門 - Stackのインストールと設定
19            Ruby内にHaskellのコード埋め込むHaskellというGem作ったヨ!
20                    Typing Haskell in Haskellを読んでみる
21                   VisualStudioCodeでHaskell開発環境を整える
22                                   なぜHaskellを学ぶと良いか
23         [Haskell] Some memo about learning haskell
24                                   Haskell インストールメモ
25  VSCodeでCouldn't start client Haskell IDEが出る(Wi...
26                          Stackをhaskell-modeで使ってみよう
27                         Haskellのお勉強その1-Haskell環境構築
28                              HaskellerがRustに入門してみた
29                            Haskellの入門から中級者になるまでの指針
30                                Atom EditorでHaskell
31                            Haskellで逆ポーランド記法の計算機を作る
32                       Atomエディタでide-haskellを使うまでの手順
33                            MacでHaskellを触ってみるメモ 0.1
34                                      Haskellを始めてみた
35                      ATOMのide-haskell導入手順(MacOS X)
36                       【翻訳】PureScriptとHaskellの違い +α
37                                          Haskellメモ
38                            Windows10でHaskell開発環境構築
39                                  Haskellで食べていけるよ!!
40                Haskell Weekly News 日本語版(お試し) (5/8)
41                           世界のHaskell専門家に向けたメッセージ全文
42    JSON から各言語のコードを生成する quicktype の Haskell 出力を実装した
43                               haskell-ide-engine導入
44                    macOSでVS CodeのHaskellの環境構築で嵌った点
45                              Go製のToolをHaskellで実装する
46                                 Haskellの($)と(.)の違い
47                       Samuel Gélineau からの返信その1(翻訳)
48                                    Haskell 環境構築 メモ
49               Haskellerの1週間Rust入門チャレンジ Day 1 #Rust

                                               記事のURL
0   http://qiita.com/Tatsuki-I/items/6d4a2d9f767ae...
1   http://qiita.com/mod_poppo/items/418da906f6621...
2   http://qiita.com/hiratara/items/169b5cb83b0adb...
3   http://qiita.com/sgmryk/items/bc99efe36ad1c910...
4   http://qiita.com/sparklingbaby/items/a46f299dd...
5   http://qiita.com/oskats1987/items/30f9078c5096...
6   http://qiita.com/atsuyoshi-muta/items/9dd10d48...
7   http://qiita.com/dd0125/items/a141000ead36b382...
8   http://qiita.com/oskats1987/items/dcd46780ff5e...
9   http://qiita.com/Izawa_/items/ed0579a0e7d93e5c...
10  http://qiita.com/Tatsuki-I/items/d1d122107da8c...
11  http://qiita.com/satosystems/items/32bf104a041...
12  http://qiita.com/a163236/items/5e0d0e373e87ca8...
13  http://qiita.com/takenobu-hs/items/b95f0a4409c...
14  http://qiita.com/pumbaacave/items/17e6699d4db8...
15   http://qiita.com/F_cy/items/9c49e351196943e38ad9
16  http://qiita.com/nka0i/items/d44f0c6d4df1ef582fd3
17  http://qiita.com/zhupeijun/items/4abcc5fa1cdce...
18  http://qiita.com/sparklingbaby/items/a901cb3a7...
19  http://qiita.com/gogotanaka/items/78a3ffd04abc...
20  http://qiita.com/nka0i/items/d44f0c6d4df1ef582fd3
21  http://qiita.com/legokichi/items/8e7a68ffee522...
22  http://qiita.com/arowM/items/0305d4f439752f285438
23  http://qiita.com/zhupeijun/items/4abcc5fa1cdce...
24  http://qiita.com/tnoda_/items/22b265fe9ad8ee1e...
25  http://qiita.com/yutasth/items/28af2eb0371f645...
26  http://qiita.com/t-mochizuki/items/d831df3a920...
27  http://qiita.com/CPyRbJvCHlCs/items/9da9b43b55...
28  http://qiita.com/kanimum/items/d89547235070038...
29  http://qiita.com/Lugendre/items/70e517e59698e0...
30  http://qiita.com/eielh/items/b2e85f8ea4c6cdb8012d
31  http://qiita.com/inatatsu_csg/items/b035c76ec6...
32  http://qiita.com/busyoumono99/items/220bd3c30f...
33  http://qiita.com/hiroyuki_hon/items/3eb41a16fe...
34  http://qiita.com/Cj-bc/items/583fa82805775cf17dd6
35  http://qiita.com/nakamurau1@github/items/7feae...
36  http://qiita.com/hiruberuto/items/3eb21ef81b3d...
37  http://qiita.com/sahara/items/7c7ef646fb3e9b08...
38  http://qiita.com/kitsukitsuki/items/a56cbfc0de...
39  http://qiita.com/reotasosan/items/e80ab706baef...
40  http://qiita.com/imokurity/items/f90e4c35c74fe...
41  http://qiita.com/reotasosan/items/2b37fdef025a...
42  http://qiita.com/algas/items/1ebb9b8c77fc5f344708
43  http://qiita.com/dyoshikawa/items/a1789bf7ff1d...
44    http://qiita.com/dsm/items/861d08844b1fba32f07b
45  http://qiita.com/kwhrstr1206/items/fdf460f2a9a...
46  http://qiita.com/TTsurutani/items/201200c1f288...
47  http://qiita.com/reotasosan/items/cce796d32105...
48  http://qiita.com/1ain2/items/09ad8b0e4992f7ceae0f
49  http://qiita.com/Tatsuki-I/items/e19953c051e55...
$ 

( 出力ファイル群 )

スクリーンショット 2020-11-08 0.27.17.png

( Excelファイル )

スクリーンショット 2020-11-08 0.29.50.png

( pngファイル )

スクリーンショット 2020-11-08 0.30.42.png

( 途中ページの画面キャプチャ画像ファイルは、掲載省略)

スクリーンショット 2020-11-08 0.31.21.png

その他:記事の検索文字列は、漢字カタカナかなもOK

Console
$ python  selenium_python_multi_pages_while.py -word 圏論 -max 20
4
5
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
4
5