Pythonスクレイピングseleniumu初心者向け動画付解説

python selenium

Pythonによるスクレイピングの方法について解説していきます

インターネットから欲しい情報を得るためには、
下記のような手作業が発生します

  • webサイトにアクセス(url入力)
  • キーワード入力したり(google検索エンジンなど)
  • 何回かクリック操作(webサイト内を検索)
  • 欲しい情報をファイルにまとめる

この記事を読むと上記の作業をPythonが実行してくれるようになりとても便利なります

まずはどのようなことができるかについて下の動画をご覧ください

▼動画の概要

  • googleホームページにアクセス
  • 検索キーワードに、「nobushige.com」入力 ~ Enter押下
  • 検索結果の1位をクリック
    (nobushige.com(nobby blog)が表示される)
  • PROGRAMMING(カテゴリ)クリック
    (PROGRAMMINGの記事が表示される)
  • 各記事の情報(投稿日、タイトル、カテゴリ、アイキャッチ画像、url、スニペット)を取得
  • csvファイルに保存

この記事では、nobushige.com(nobby blog)を例として説明しています
この操作はとても汎用性がひろく、ID&パスワードを入力してログインするタイプのwebサイト全般に使用できます
またwebサイト上の情報を一括で取得することもできるので、マーケティング関係など情報収集系の業務に使用できます

Jupyter Lab起動

Jupyter Labがインストールされていない方は下記の記事にインストール方法の説明がありますので参考にしてください
該当箇所は、目次からとどって、「2. エディタ入手」 >> 「2. Jupyter Lab(ジュピターラボ)入手」 にあります

Pythonめ始め方初期費用ゼロオフラインでもOK(Windows版)
Python初め方初期費用ゼロオフラインでもOK(Windows版) Pythonインストール ライブラリ エディタ バッチファイル PIPが使えない場合も方法あり VS Code JupyterLab パソコンの設定 パスを通す簡単なコードを実践あり

Jupyter Labを起動させます

コマンドプロンプトを起動(Winボタン ~ 「cmd」)
juputer lab

を記述してEnter押下
これでJupyter Labが起動します
ここではファイル名をわかりやすく「selenium.ipynb」としています

コードの説明

この記事で取り扱うPythonのコードについて説明してきます

ライブラリのインポート

下記のコードを記入してライブラリをインポートします
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from webdriver_manager.chrome import ChromeDriverManager
import pandas as pd
from time import sleep
これらのライブラリが事前にインストールされていることが前提となります

まだライブラリがインストールされていない場合は、下記の記事にライブラリのインストール方法の説明がありますので参考にしてください
該当箇所は、目次からたどって、「3.ライブラリ入手」にあります

Pythonめ始め方初期費用ゼロオフラインでもOK(Windows版)
Python初め方初期費用ゼロオフラインでもOK(Windows版) Pythonインストール ライブラリ エディタ バッチファイル PIPが使えない場合も方法あり VS Code JupyterLab パソコンの設定 パスを通す簡単なコードを実践あり

ライブラリがインストールされているかどうかの確認はコマンドプロンプトから確認可能です

コマンドプロンプト起動(Winボタン ~ 「cmd」)
pip list

を記述してenter押下
インストールされているライブラリの一覧が表示されます
ライブラリの名前が表示されている場合はインストール済みです

インポートするライブラリについて一つずつ解説していきます
from selenium import webdriver

seleniumからwebdriverをインポートしています
このwebdriverを仲介してブラウザを操作していきます
目的のwebサイトにアクセスしたりできるようになります

ブラウザ:Google Chrome, Internet Explore, Microsoft Edge などホームページを表示するもの

selenium.webdriver.common.keys import Keys

「Enter」などのキー操作ができるようになります

webdriver_manager.chrome import ChromeDriverManager

スクレイピングには、各ブラウザ用の「ドライバ」をダウンロードする必要があります
しかもブラウザが更新される度に、更新されたブラウザに適合したドライバをその都度ダウンロードする必要があります
これは結構面倒です(怒)
このような面倒な作業を自動で実行してくれるのがwebdriver_managerです
これをインポートしておくと自動的に現在のブラウザに適したドライバを自動でダウンロードしてくれます
これはとても便利です!!(おすすめです)

import pandas as pd

pandasをpdという名前でインポートします
毎回pandasと書くのが手間なので、代わりにpdと書いても使用できるようにしています

今回は複数のデータを取得します
記事の個数 ✕ 複数項目
このような複数のデータの塊をデータフレームという形でまとめてcsv形式で保存してくれるのがpandasとなります

from time import sleep

time から sleepをインポートしています
webサイト上でクリック操作をして次のページに切り替わるまで若干時間がかかる場合があります
この切り替わり時間を見越して、待機時間を作ってくれるのが time の sleep となります
プログラミングは何も指定がしないと次々にコードを実行していきますので
意図的に待機時間を作って上げる必要があります

変数の設定

下記のコードを入力して各変数に値を代入しておき後々操作しやすいようにしておきます
url = ‘https://www.google.com/’
cols = [‘投稿日’,’タイトル’,’カテゴリ’,’URL’,’アイキャッチ’,’スニペット’]
df = pd.DataFrame(columns=cols)
b=webdriver.Chrome(ChromeDriverManager().install())
最初にアクセスするgoogle の url (‘https://www.google.com/’)を 「url」という変数に格納しています
url = ‘https://www.google.com/’
cols = [‘投稿日’,’タイトル’,’カテゴリ’,’URL’,’アイキャッチ’,’スニペット’]

収集した情報をcsvファイルで保存します
収集した情報として、
‘投稿日’
‘タイトル’
‘カテゴリ’
‘URL’
‘アイキャッチ’
‘スニペット’
があります
保存先のファイルに先に名前をつけておきここに収集したデータを格納していきます

df=pd.DataFrame(columns=cols)

pandasのDataFrameメソッドで空のデータフレームを作っておきます

データフレーム:縦✕横にデータをまとめる2次元的な形式

A B C
a 1 2 3
b 4 5 6
c 7 8 9

b=webdriver.Chrome(ChromeDriverManager().install())

現在のブラウザのバージョンに適したドライバをインストールしてbに代入します

ChromeDriverManager(ドライバ自動インストール)がうまく動かない場合は
代わりに下記のコードをご使用ください

b=webdriver.Chrome(executable_path=r’C:\Users\●●●●\Documents\Python\public_package\chromedriver.exe’)

(社内ネットワークの設定の関係で、ChromeDriverManagerが使用できない場合があります)

●●●● の箇所は、ご使用のPCによって異なります

※ selenium v4.3.0から、webdriver.Chrome(executable_path=r”…\chromedriver.exe”) が使用できないことがあります(2022年6月24日から)
 対処法①:以前のバージョン(selenium v4.2.0)を使用する
 対処法②:新しい記述方法に書き換える

以前の記述方法(こちらを削除)
b= webdriver.Chrome(executable_path=r”…\chromedriver.exe”)
新しい記述方法(こちらを追記)
from selenium.webdriver.chrome import service as fs
CHROMEDRIVER = r”…\chromedriver.exe”
chrome_service = fs.Service(executable_path=CHROMEDRIVER)
b = webdriver.Chrome(service=chrome_service)
この場合は、事前にchromedriverをダウンロードして手元のPCに保存しておく必要があります

‘C:\Users\●●●●\Documents\Python\public_package\chromedriver.exe’ の部分は、
chromdriverを保存している場所のフルネームとなります

●●●● の箇所は、ご使用のPCによって異なります

chromedriverの入手

chromedriverの入手方法です
手元のPCのブラウザ(Chrome)のバージョンに対応しているchromedriverが必要となります
そのため、先ずは手元のPCのブラウザのバージョンを確認します

手元のPCのブラウザのバージョンを確認

手元のPCのブラウザのバージョンを確認する手順です

  • Google Chrome起動
  • 「Google Chromeの設定」クリック
  • 「ヘルプ」~「Google Chromeについて」クリック

バージョンの右側に数字(例 104.0.5112.102)が表示されています
これが手元ののPCのブラウザのバージョンとなります

chromedriverのダウンロード

chromedriverはこちらのサイトからダウンロードできます
https://chromedriver.chromium.org/downloads

ここで手元のPCのブラウザと同じものを選択します(例 104.0.5112.79)
「chromedriver win32.zip」をクリック(※ OSがWindowsの場合)
クリックスをするとダウンロードが始まります
zipファイルを開くと「chromedriver.exe」というファイルがあります
これがchromedriverです
わかりやすいところに保管しておきます

「nobushige.com(nobby blog)」にアクセス(google経由)

下記のコードを入力して「nobushige.com(nobby blog)」にアクセスします
b.get(url)
e = b.find_element_by_class_name(‘gLFyf’)
e.send_keys(“nobushige.com”)
e.send_keys(Keys.ENTER)
e = b.find_element_by_class_name(‘MjjYud’).find_element_by_tag_name(‘a’)
e.click()
sleep(1)
e=b.find_element_by_id(‘navi-in’).find_element_by_link_text(‘PROGRAMMING’)
e.click()

googleのサイトにアクセス

googleのサイトにアクセスします
b.get(url)

検索ボックスにキーワードを入力

検索ボックスにキーワードを入力します

e = b.find_element_by_class_name(‘gLFyf’)
e.send_keys(“nobushige.com”)

googleの検索ボックスにキーワードを入力します
そのためには、googleの検索ボックスの要素を特定する必要があり、デベロッパーツールを使っていきます

デベロッパーツール:Google Chromeに標準搭載されている開発者用の検証ツール
webサイトはhtml方式で記述されており、その記述内容を確認することができます
他にもいろんなことができますが、ここでは要素と特定するために使用します

デベロッパーツールでgoogleの検索ボックスの要素を特定していきます

「Ctr + Shift + I」で、デベロッパーツールが表示されます
「Select an element in this page to inspect it」をクリック (または「Ctr + Shift + C」クリック)

この状態で、googleの検索ボックスをクリック
<input class=”gLFyf gsfi”…

と表示された箇所の背景が水色になり強調されます
ここがgoogleの検索ボックスの要素となります

このようにして要素を見つけていきます

次はこの要素を変数に代入していきます
class = “gLFyf”

となっていたので、属性名=class、属性値=”gLFyf”で要素を特定します

bの要素の中で、属性名=class + 属性値=”gLFyf” の要素を e に代入しています
.find_element_by_class_name() は、class名で要素を取得するseleniumのメソッドです

※ selenium v4.3.0から、.find_element_by_ が廃止されています(2022年6月24日から)
これが原因で、.find_element_by_ が使用できないことがあります

  対処法①:以前のバージョン(selenium v4.2.0)を使用する
  対処法②:新しい記述方法に書き換える
  変更点 .find_element_by_ → .find_element(By.)
例 .find_element_by_class_name(“文字列”) → .find_element(By.CLASS_NAME,”文字列”)
また、「By.」を使用可能とするため
「from selenium.webdriver.chrome.by import By」の追記が必要となります

要素を特定したらここへ文字列を代入します
e.send_keys(“nobushige.com”)

.send_keysは、( )内の文字列を要素に送信するseleniumのメソッドです

e.send_keys(Keys.ENTER)

.send_keys(Keys.ENTER)は、enterキーを押下するseleniumのメソッドです

これでgoogleのwebサイトにアクセスして
検索ボックスに「nobushige.com」を入力し
enterキーを押下するところまでできました
これで検索結果が表示されます

「nobby blog」をクリック

「nobby blog」と表示されているリンクの要素を取得していきます

「nobushige.com」の検索結果で検索1位のところに「nobby blog」があります

この「nobby blog」をクリックしていきます
e = b.find_element_by_class_name(‘MjjYud’).find_element_by_tag_name(‘a’)
e.click()

上記同様に、
デベロッパーツールを表示(「Ctr + Shift + I」クリック)
「Select an element in this page to inspect it」をクリック (または「Ctr + Shift + C」クリック)

この状態で、nobby blogをクリックすると
<h3 class=”…”nobby blog><h3>

の背景が水色になり強調されます
これはテキストが表示されているだけですのでurlがあるaタグを探します

少し上を見ると
< a href=”https://nobushige.com/”>

があります。これが取得したい要素

更に上を見ていくと
<div class=”MjjYud”>

があり、その左にある▼をクリックしてみます

すると
<div class=”MjjYud”></div>

が折りたたまれて

複数の
<div class=”MjjYud”></div>

が表示されます

状況を整理すると

複数の
<div class=”MjjYud”></div>

があり

<div class=”MjjYud”>

の中に

<a href=”…”></a>

がある

欲しいのは、複数ある
<div class=”MjjYud”>
の内、最初の
<div class=”MjjYud”>
そして、この中にある
<a href=”…”></a>

が欲しい要素となります

.find_element_by_class_name(‘MjjYud’)
を使うことで、

最初の
<div class=”MjjYud”>

を取得できます

更に
.find_element_by_tag_name(‘a’)
をつながることで

この中にある
<a href=”…”></a>

を取得することができます

.click() は要素を(左)クリックするseleniumのメソッドです

sleep(1)

webサイトの画面が切り替わるまで少し待機時間があるので、
1秒待ちます
もしこの設定をしなかったらwebサイトの画面が切り替える前に次のコードが実行してしまい
エラーになってしまいます
そのためwebサイトの画面が切り替わるタイミングでは、sleepを使って待機時間を確保しましょう

これで「nobby blog」がクリックされ
「nobby blog」が表示されます

「PROGRAMMING」をクリック

次はカテゴリーの「PROGRAMMING」をクリックします

「PROGRAMMING」と表示されているリンクの要素を取得していきます

これを実行するためのコードは下記となります

e=b.find_element_by_id(‘navi-in’).find_element_by_link_text(‘PROGRAMMING’)
e.click()

先ほどと同様にデベロッパーツールを表示して要素を見つけていきます
デベロッパーツールを表示(「Ctr + Shift + I」クリック)
「Select an element in this page to inspect it」をクリック (または「Ctr + Shift + C」クリック)
この状態で、PROGRAMMINGをクリックすると

<div class=”item-label”>PROGRAMMING</div>

の背景が水色になり強調されます

「PROGRAMMING」というテキストがある要素ではありますが他にもこのような要素はあるので
もう少し範囲を絞っていきます
属性名idは、ページ内で属性値が一つしか持つことができないというルールがあります
今回の場合に要素を特定するときは、属性名idを見つけて範囲を絞っていきます

先ほど見つけた要素の上の方を見ていくと、

<nav id=”navi-in” …

があります。今回はこれを利用します

状況は、

<nav id=”navi-in” …

の中に、

<div class=”item-label”>PROGRAMMING</div>

があり、これが今回取得したい要素となります

.find_element_by_id(‘navi-in’)
を使って、

<nav id=”navi-in” …

を取得します
続けて、
.find_element_by_link_text(‘PROGRAMMING’)
をつなげることで、この中にある

<div class=”item-label”>PROGRAMMING</div>

を取得します
.find_element_by_link_text は、リンクテキストで要素を検索するseleniumのメソッドです

※ selenium v4.3.0から、.find_element_by_ が廃止されています(2022年6月24日から)
これが原因で、.find_element_by_ が使用できないことがあります

  対処法①:以前のバージョン(selenium v4.2.0)を使用する
  対処法②:新しい記述方法に書き換える
  変更点 .find_element_by_ → .find_element(By.)
例 .find_element_by_link_text(“文字列”) → .find_element(By.LINK_TEXT,”文字列”)
また、「By.」を使用可能とするため
「from selenium.webdriver.chrome.by import By」の追記が必要となります

.click() で取得した要素を(左)クリックします

これで「nobby blog」の中のカテゴリー「PROGRAMMING」のページが表示されます

情報取得

下記のコードで記事の中から欲しい情報を取得していきます
ここでは
投稿日
タイトル
カテゴリ
アイキャッチ画像のURL
記事のURL
スニペット(概要)
を取得していきます

es=b.find_element_by_id(‘list’).find_elements_by_tag_name(‘a’)
for e in es:
post_date = e.find_element_by_class_name(‘post-date’).text
title = e.get_attribute(‘title’)
category = e.find_element_by_class_name(‘cat-label’).text
url = e.get_attribute(‘href’)
eyecatch = e.find_element_by_tag_name(‘img’).get_attribute(‘src’)
snippet = e.find_element_by_class_name(‘entry-card-snippet’).text
s = pd.Series([post_date,title,category,url,eyecatch,snippet],index=df.columns)
df = df.append(s,ignore_index=True)

先ほどと同様にデベロッパーツールを表示して要素を見つけていきます

デベロッパーツールを表示(「Ctr + Shift + I」クリック)
「Select an element in this page to inspect it」をクリック (または「Ctr + Shift + C」クリック)
この状態で、投稿日をクリックすると

<span class=”post-date”>…</span>

の背景が水色になり強調されます
これが欲しい要素ですが、記事は複数あるので記事毎に要素を確認するのは手間がかかります
そこで、各記事の中に投稿日やタイトルなどが同じように格納されているはずなので
先ずは各記事の要素(投稿日やタイトルなどが格納されている大きな要素)を取得していきます
先ほど見つけた要素の上の方を見ていくと

<a href=”…”>…</a>

があります。これの左側の▼をクリックすると格納され

<a href=”…”>…</a>

が複数並んでいます
これが各記事の要素(投稿日やタイトルなどが格納されている大きな用途)となります
更にその上を見ると

<div id=”list”>…

があります
状況を整理すると

<div id=”list”>…

といういう要素の中に複数の

<a href=”…”>…</a>

という要素が格納されています
更に各要素の中に
投稿日やタイトルなどの要素が格納されています

先ほどまでは、
.find_element_by_tag_name()
を使って、検索で見つかった最初の要素を取得していました

今回は複数の要素を取得したいので
.find_elements_by_tag_name()
を使っていきます
※ element と elements 「s」があるかないかの違いです

es=b.find_element_by_id(‘list’).find_elements_by_tag_name(‘a’)

先ず、
.find_element_by_id(‘list’)
で、

<div id=”list”>…

という要素を取得します
続けて、
.find_elements_by_tag_name(‘a’)
をつなげることで
この中に格納されている

<a href=”…”>…</a>

という要素を全て取得します

複数の要素を取得しましたので
取得した複数の要素から一つずつ要素を取り出して
処理していきます
そのために下記のようなfor文を使っていきます

for e in es:

es の中にある要素を一つずつ取り出して、e に代入するという意味となります

取り出した一つずつの要素から
投稿日、タイトル、カテゴリ、url、アイキャッチのurl、スニペットを抽出していきます

post_date = e.find_element_by_class_name(‘post-date’).text
title = e.get_attribute(‘title’)
category = e.find_element_by_class_name(‘cat-label’).text
url = e.get_attribute(‘href’)
eyecatch = e.find_element_by_tag_name(‘img’).get_attribute(‘src’)
snippet = e.find_element_by_class_name(‘entry-card-snippet’).text

投稿日は、
デベロッパーツールで投稿日をクリックすると

<span class=”post-date”>…</span>

という要素に、投稿日があります
.find_element_by_class_name(‘post-date’)
を使って、要素を取得します
更に
.text
をつなげることで取得した要素内のテキスト情報を取得します
取得したテキスト情報をpost_dateに格納します

タイトルは、

<a href=”…” title=”…”></a>

同じ要素内の title=”” のところにあります
この場合は、取得した要素に
.get_attribute(‘title’)
をつなげることで
title=”” のところの情報を取得できます
取得した情報をtitleに格納します

カテゴリは、
デベロッパーツールでPROGRAMMINGをクリックすると

<span class=”cat-label”>…</span>

という要素が見つかります
.find_element_by_class_name(‘cat-label’)
を使って

<span class=”cat-label”>…</span>

という要素を取得し
.text
をつなげることで取得した要素内のテキスト情報を取得します
取得したテキスト情報をcategoryに格納します

urlは、

<a href=”…”>…</a>

の中のhref=”” のところとなります
この場合は要素に
.get_attribute(‘href’)
をつなげることで取得できます
取得した情報をurlに格納します

アイキャッチ画像は、

<img src=”…”>

の src=”…” のところにあります
先ず
.find_element_by_tag_name(‘img’)
を使って

<img …>

という要素を取得し、続けて
.get_attribute(‘src’)
をつなげることで
src=”…”のところを取得します
取得した情報をeyecatchに格納します

スニペットは、

<div class=”entry-card-snippet”>…</div>

という要素にあります
.find_element_by_class_name(‘entry-card-snippet’)
を使って

<div class=”entry-card-snippet”>…</div>

という要素を取得します、更に
.text
をつなげることでこの中にあるテキスト情報を取得します
取得したテキスト情報をsnippetに格納します

各変数(post_date, title, category, url, eyecatch, snippet)に格納したバラバラの情報を
配列として一つに格納します

s = pd.Series([post_date,title,category,url,eyecatch,snippet],index=df.columns)

.Series
を使うことで複数の情報を配列で格納できます
[ ](角かっこ)の中に複数の情報を代入し、「,」(カンマ)で区切ります
index=df.columns
を記述することで見出しは、df.columnsと同じものを使うことができます
複数の情報を格納した配列を s に格納します

複数の情報を配列で格納したら
今度は配列自身も複数あるので
複数の配列を一つのデータフレームに格納します

df = df.append(s,ignore_index=True)

.append
を使うことでデータフレームに配列を追加していくことができます
( )内に、s を記述することで s という配列を追加しています
ignore_index=True
を記述することで縦方向の見出しは省略されます
※ 配列をデータフレームに追加するときは縦方向の見出しは不要ですのでこのように記述します

csvファイルとして保存

これで各記事の中にある情報(投稿日やタイトルなど)を
一つのデータフレームに格納できました
次はこのデータフレームの情報をcsv形式で保存します

df.to_csv(r’C:\Users\●●●●\desktop\nobushige.com.csv’,encoding=’utf-8-sig’)

●●●● の箇所は、ご使用のPCによって異なります

.to_csv
を使うことでデータフレームの情報をcsv形式で保存します
( )内には、保存先とファイル名を記述します
保存先を省略する場合は、ipynbファイルと同じ場所に保存されます
encoding=’utf-8-sig’
を記述することで日本語フォントの文字化けを防止ます
※ これをしていないと日本語フォントは文字化けしていしまいます
pandasでデータフレームをcsv形式で保存する場合はencoding=’utf-8-sig’をします

コードの起動

Jupyter Lab に記述したコードを起動させます

Jupyter Labの画面で
Run the selected cells and advenceをクリック(または、「Shift + Enter」)
これでコードが起動します

この記事で使用した.ipynbファイルはこちらからどうぞ

selenium.ipynbのzipファイル

今回は Python のselenium を使ってスクレイピングの方法について解説しました
題材として「nobby blog」を使用しました
webサイトにアクセス ~ ID/パスワード入力 ~ クリック という作業はよくある作業です
これを自動化するととても便利です
私も「webサイトにアクセス ~ ID/パスワード入力 ~ クリック」でログインするwebサイトは
ほとんどPythonで自動化しています
とても便利でもう元には戻れないと思います
この便利さを皆様にも体験していただけると幸いです

コメント

この記事が気に入ったら
いいね!しよう
最新情報をお届けします。
タイトルとURLをコピーしました