Pythonのsleniumでスクレイピング - ログインしてファイルダウンロードする - ※この記事は個人的な備忘録です
はじめに
- この記事は個人的な備忘録です。
- 業務で使用するためのサンプルツール用のコードなどを記述します。書きかけのコードもあります。
- あくまでサンプルのため、コードの実践は自己責任でお願いします。
概要
まずはselenumが適用できるかチェックをする
コード
# WebドライバーでChromeを開く from selenium import webdriver driver_file = r'C:\Users\自分のフォルダ\ドライバのパス\chromedriver.exe' browser = webdriver.Chrome(driver_file) url = 'ログインしたいサイトのURL' browser.get(url) # 以下テスト用 # ()内はクラスやIDを調べて編集する browser.title # ログインIDを入力 login_id = browser.find_element_by_name("login") login_id.send_keys("ログインIDを入力") # パスワードを入力 password = browser.find_element_by_name("passwd") password.send_keys("パスワードを入力") #ログインボタンをクリック login_btn = browser.find_element_by_name("btnSubmit") login_btn.click() #2秒待機 #チェックボックスをクリック check = browser.find_element_by_class_name("checkbox") check.click() time.sleep(2) #ダウンロードボタンをクリック dlbtn = browser.find_element_by_class_name("downlord") dlbtn.click() browser.quit()
Excel VBAを使ってセル範囲を配列に格納するには - 動的配列2 - (2次元配列の1次元目のインデックス範囲を変更したいとき)
はじめに
前回は、セル範囲を動的配列に格納する方法(2次元目のインデックス範囲を変更)について説明しました。
今回はセル範囲を動的配列に格納する方法(1次元目のインデックス範囲を変更)について説明します。
◆目次◆
Transpose関数
先に今回の肝となる「Transpose関数」を紹介します。
- Transpose関数:行と列を入れ替える関数
Excelのワークシート上で、右クリックで貼り付けするときに出てくる「行/列の入れ替え」と同じことができます。
使い方は以下のとおりです。
WorksheetFunction.Transpose(行と列を入れ替えたいセル範囲や配列)
Transpose関数の実例は、次の節で説明します。
1次元目のインデックスの範囲の変更
さて、ここが山場です。
以前の記事で、動的配列について以下のように書きました。
ただし、ReDim Preserveステートメントを使って変更できるのは「配列の最後の次元のみ」ということに注意が必要です。
つまり、「2次元配列において、1次元目のインデックス範囲は変更できない」ということです。
でも、1次元目のインデックス範囲を変更したいことは多々あります。 そこで、先ほど紹介したTranspose関数が活躍します!
先に、マクロに記述する手順を説明をします。イメージは以下の画像を参照してください(立方体に書いている文字は、セルの位置を指します)。
- 変数:lastRowsを宣言し、Sheet1の最下行番号を代入する
- 配列の変数:sampleDataArrayを宣言する
- For Next構文でセルの値を変数:sampleDataArrayへ格納する(わざと行と列を入れ替えて値を格納します、画像を参照してください)
- 新しい配列の変数:sampleDataArray_2を宣言する
- 変数:sampleDataArrayを、Transpose関数で行と列を入れ替えて変数:sampleDataArrayArr_2に格納する(画像を参照してください)
つまり、手順の3と5の、計2回「行と列を入れ替え」が発生していることになります。
この流れをコードにすると、以下のとおりです(コメントアウトしている①と②は後ほど説明します)。
Sub dataArray2_3() '1. 変数:lastRowsを宣言し、Sheet1の最下行番号を代入する Dim lastRows As Long lastRows = Sheet1.Cells(Rows.Count, 1).End(xlUp).Row '2. 配列の変数:sampleDataArrayを宣言する Dim sampleDataArray As Variant '3. For Next構文でセルの値を変数:sampleDataArrayへ格納する(わざと行と列を入れ替えて値を格納する) Dim i As Long For i = 1 To lastRows ReDim Preserve sampleDataArray(1 To 5, 1 To i) sampleDataArray(1, i) = Sheet1.Cells(i, 1).Value sampleDataArray(2, i) = Sheet1.Cells(i, 2).Value sampleDataArray(3, i) = Sheet1.Cells(i, 3).Value sampleDataArray(4, i) = Sheet1.Cells(i, 4).Value sampleDataArray(5, i) = Sheet1.Cells(i, 5).Value Next i ' With Sheet2 '① ' .Range(.Cells(1, 1), .Cells(UBound(sampleDataArray, 1), UBound(sampleDataArray, 2))).Value = sampleDataArray ' End With '4. 新しい配列の変数:sampleDataArray_2を宣言する Dim sampleDataArray_2 As Variant '5. 変数:sampleDataArrayを、Transpose関数で行と列を入れ替えて変数:sampleDataArrayArr_2に格納する sampleDataArray_2 = WorksheetFunction.Transpose(sampleDataArray) ' With Sheet3 '② ' .Range(.Cells(1, 1), .Cells(UBound(sampleDataArrayArr_2, 1), UBound(sampleDataArrayArr_2, 2))).Value = sampleDataArrayArr_2 ' End With End Sub
実際に上記のコードで配列がどのように変わっていくのかを確認したい方は①と②のコメントアウトを解除してください。
①のコメントアウトを解除したら、行と列が逆転した配列をSheet2に貼り付けできます。
②のコメントアウトを解除したら、もう一度行と列を逆転させた配列をSheet3に貼り付けできます。
おわりに
いかがでしょうか。
セル範囲を動的配列に格納する方法(1次元目のインデックス範囲を変更)は2回も、行と列を入れ替えているので、最初は違和感があると思います。しかし、何度かコードを書いていくうちに慣れていくので、ぜひ試してください。
次回は配列を使った時の可読性を上げるための方法を説明します。
Excel VBAを使ってセル範囲を配列に格納するには - 動的配列1 -
はじめに
前回は、セル範囲を静的配列に格納する方法を説明しました。
今回は、配列のインデックス範囲を求める関数と、セル範囲を動的配列に格納する方法を説明します。
◆目次◆
Lboud関数とUbound関数
配列のインデックス範囲を求める関数、「Lboud関数」と「Ubound関数」を紹介します。
- Lbound関数:配列のインデックスの範囲の下限を求める関数
- Ubound関数:配列のインデックスの範囲の上限を求める関数
使い方は以下のとおりです。
LBound(配列の変数, インデックス範囲の下限を求めたい次元) UBound(配列の変数, インデックス範囲の上限を求めたい次元)
前回作成したdataArray1_4プロシージャを引用して、使用例をお見せします。
Sub dataArray1_4() Dim sampleDataArr As Variant sampleDataArr = Sheet1.Cells(1, 1).CurrentRegion.Value End Sub
このコードは、CurrentRegionプロパティを使って「セルA1を含むデータ有効範囲」を指定し、セルの値を配列に格納しています。
この配列に対して追加の処理を行いたい場合、配列のインデックス範囲を指定する必要があります。
Lboud関数とUboud関数を使うと配列のインデックス範囲がわかります。
例として、イミディエイトウィンドウを使って、配列sampleDataArrのインデックス範囲を出力します。
Sub dataArray1_4_1() Dim sampleDataArr As Variant sampleDataArr = Sheet1.Cells(1, 1).CurrentRegion.Value '1次元目のインデックス範囲を求める Debug.Print "1次元目のインデックス範囲は" & LBound(sampleDataArr, 1) & "から"; UBound(sampleDataArr, 1) & "まで" '出力結果:1次元目のインデックス範囲は1から619まで '2次元目のインデックス範囲を求める Debug.Print "2次元目のインデックス範囲は" & LBound(sampleDataArr, 2) & "から" & UBound(sampleDataArr, 2) & "まで" '2次元目のインデックス範囲は1から5まで End Sub
ローカルウィンドウで配列sampleDataArrの範囲を調べても、上記のコードの結果と一致しますね。
では、今回の本題である動的配列でセル範囲を指定して配列に格納する方法を説明します。
動的配列でセル範囲を指定して配列に格納する
前回と同じサンプルデータを使用します。この表は619行目まで記入されています。
動的配列でセルの値を取得する場合は、For Next構文でループを使って配列の大きさを変更します。
1次元配列の場合
では、サンプルデータの1行目の値を、配列に格納します。
Sub dataArray2_1() Dim lastColumns As Long lastColumns = Sheet1.Cells(1, Columns.Count).End(xlToLeft).Column Dim sampleDataArray() As Variant Dim i As Long For i = 1 To lastColumns ReDim Preserve sampleDataArray(1 To i) sampleDataArray(i) = Cells(1, i).Value Next i End Sub
手順は、配列の変数をVariant型で宣言して、カウント用の変数iをFor~Next関数ににへ配列に格納したいセル範囲を指定します。 今回はColumns.countを使って一番右の列番号を取得して、セルの範囲指定します
2次元配列の場合
2次元配列の場合は、「1次元目のインデックスの範囲」「2次元目のインデックスの範囲」のどちらを変更するかで、書き方が変わります。
2次元目のインデックスの範囲の変更
列方向のインデックスの範囲を変更する方法は、 さすがに619行目まで書くのは大変なので、3行目までを配列に入れたいと思います。
Sub dataArray2_2() Dim lastColumns As Long lastColumns = Sheet1.Cells(1, Columns.Count).End(xlToLeft).Column Dim sampleDataArray() As Variant Dim i As Long For i = 1 To lastColumns ReDim Preserve sampleDataArray(1 To 3, 1 To i) sampleDataArray(1, i) = Cells(1, i).Value sampleDataArray(2, i) = Cells(2, i).Value sampleDataArray(3, i) = Cells(3, i).Value Next i End Sub
変数iの範囲は、1次元目の時と同じで一番右の列までとします。
ローカルウィンドウを見ても、サンプルデータの3行の値が配列に格納されています。
行方向(1次元目)のインデックスの範囲を変更する方法は長くなるため、次回説明します。
さいごに
実務では2次元目のインデックスの範囲を変える機会は少ないと印象です。
1次元目のインデックスの範囲の変更の方が多いと思いますが・・・少しコードの書き方にクセがあるので、できるだけわかりやすく説明できるよう、善処いたします。
Excel VBAのクラスを学ぶ前の準備 - モジュールとプロパティ -
はじめに
少し前に、「VBAにおけるPropertyプロシージャとは何か」という記事を書きました。(現在受講中のVBAの講座内容です)
今回は、その続きで、モジュール、プロパティについて調べていきます。
◆目次◆
モジュール
モジュールの種類
- 標準モジュール
- オブジェクトモジュール
- シートモジュール
- ブックモジュール
- フォームモジュール
- クラスモジュール
大きく分けると、「標準モジュール」か、「オブジェクトモジュール」か、ということになります。
標準モジュール
標準モジュールで記述したパブリックメンバーはすべてグローバルのメンバーです。 ※グローバルなメンバー→全体的なメンバー、つまりどのオブジェクトの処理も可能
モジュールを分けてコードを管理する大きなメリットは以下2点です。
- 可動性が上がる(コードの管理がしやすい)
- 誤記防止の効果が高い
オブジェクトモジュール
オブジェクトモジュールで記述したパブリックメンバーはオブジェクトに属します。
※ほかのオブジェクトの操作もできるけど、「コードの管理」という観点から外れるので、すべきではないです。
プロパティ
オブジェクトにプロパティを追加する方法
- モジュールレベル変数
- Property Let/Setプロシージャ
- Property Getプロシージャ
セッターとゲッター
- セッター(setter)= 値をsetする(Property Let/Setプロシージャを使う)
- ゲッター(getter)= getした値を返す(Property Getプロシージャを使う)
セッター
オブジェクトモジュールに書いたプライベート変数をパブリックプロパティで値を設定すると、ほかのモジュールでもその値が使えます。
例として、好きなもの(Favorite)を設定するプロパティを作成し、セッターの役割を与えます。
[Sheet1] ' プライベート変数:favorite_ Private favorite_ As String ' パブリックプロパティ:Favorite Public Property Let Favorite(ByVal newFavorite As String) favorite_ = newFavorite End Property [Module1] Sub setter_test() Sheet1.Favorite = "Coffee" End Sub
セッターの使いどころは以下のとおりです。
- モジュールの設定に制限をかけたい
- 設定時に何らかの処理をしたい
なお、[Module1]のコードに
Debug.Print Sheet1.Favorite
を追加すると、エラーが出ます。
[Module1] Sub setter_test() Sheet1.Favorite = "Coffee" Debug.Print Sheet1.Favorite End Sub
実行結果
理由は、Property Getプロシージャを使って値を返していない(戻り値がない)からです。(Debug.Printは、getした値(戻り値)を出力する)
ゲッター
オブジェクトモジュールに書いたプライベート変数をパブリックプロパティで値を取得すると、ほかのモジュールにその値が返せます。
例として、好きなもの(Favorite)の値に「Coffee」を含む文字列が設定されていたら、コーヒーの種類を返すプロパティ(CoffeeKinds)を作成し、ゲッターの役割を与えます。
今回は、好きなもの(Favorite)の値に「AmericanCoffee」を設定します。
[Sheet1] ' プライベート変数:favorite_ Private favorite_ As String ' パブリックプロパティ:Favorite Public Property Let Favorite(ByVal newFavorite As String) favorite_ = newFavorite End Property ' パブリックプロパティ:CoffeeKinds Public Property Get CoffeeKinds() As String If Right(favorite_, 6) = "Coffee" Then CoffeeKinds = Left(favorite_, Len(favorite_) - 6) End If End Property [Module1] Sub getter_test() Sheet1.Favorite = "AmericanCoffee" Debug.Print Sheet1.CoffeeKinds '出力結果:American End Sub
ゲッターの使いどころは以下のとおりです。
- 取得時に何らかの処理をしたい
- 読み取り専用プロパティを作りたい
注意点
同名のProperty Let/SetプロシージャとProperty Getプロシージャがある場合は、読み書き可能なプロパティとして処理します。
さいごに
これらの内容をふまえたうえで、次回の講座ではクラスを勉強します。
Excel VBAを使ってセル範囲を配列に格納するには - 静的配列 -
はじめに
前回まで、Excel VBAの配列の種類について説明しました。
今回からは実際にセル範囲を配列に格納する方法を説明します。
セルの範囲を配列に格納するときの注意点
変数をVariant型で宣言しなければいけません。
また、Variant型には「異なるデータ型でも一緒に配列に格納できる」というの特性があります。
静的配列でセル範囲を指定して配列を取得する
今回はこのサンプルデータを使用します。この表は619行目までデータが記入されています。
1次元配列の場合
では、サンプルデータの1行目の値を、配列に格納します。
Sub dataArray1_1() Dim sampleDataArr As Variant sampleDataArr = Sheet1.Range("A1:E1").Value End Sub
配列用の変数をVariant型で宣言して、配列に格納したいセル範囲を指定します。
また、Columns.countを使って一番右の列番号を取得して、セルの範囲指定をすることも可能です。
Sub dataArray1_2() Dim lastColumns As Long lastColumns = Sheet1.Cells(1, Columns.count).End(xlToLeft).Column Dim sampleDataArr As Variant With Sheet1 sampleDataArr = Sheet1.Range(Cells(1, 1), Cells(1, lastColumns)).Value End With End Sub
ローカルウィンドウで配列の中身を確認すると、どちらの書き方でも同じ結果になりました。
2次元配列の場合
コードの書き方は1次元配列と同じです。このデータは619行目まであるので、セルE619までを指定します。
Sub dataArray1_3() Dim sampleDataArr As Variant sampleDataArr = Sheet1.Range("A1:E619").Value End Sub
また、CurrentRegionプロパティを使って指定したセルを含む、セルの範囲指定が可能です。
Sub dataArray1_4() Dim sampleDataArr As Variant sampleDataArr = Sheet1.Cells(1, 1).CurrentRegion.Value End Sub
ただし、CurrentRegionプロパティを使う場合は、表の途中に空白行がないことが前提となりますのでご注意ください。
配列の値をワークシートへ転記する
セルの値をほかのワークシートに転記したい場合は、以下の書き方で転記できます。
ただし、転記されるのは「配列の値」のみなので、罫線などの書式設定は転記されません。その点に注意してください。
Sub dataArray1_5() Dim sampleData As Variant sampleData = Sheet1.Range("A1:E1").Value Sheet2.Range("A1:E1") = sampleData End Sub
Sheet2に配列の値が転記できました。
さいごに
今回はセルの範囲を静的配列に格納する方法を説明しました。
静的配列の場合は、基本的なコードの書き方は「セル範囲 = 配列の変数」で良いので、そこまで難しいコードはないかと思います。
次回はセルの範囲を動的配列として格納する方法を説明します。
Excel VBAの配列にはどんな種類があるのか - 静的配列と動的配列 -
はじめに
前回は多次元配列について説明しました。
今回は静的配列と動的配列について説明します。
◆目次◆
静的配列とは
今まで、「配列は箱の集合体のようなもの」と説明しました。
静的配列は、この箱の数(配列の要素数)が決まっているときに使う配列のことです。
つまり、前回と前々回で説明していた配列は、静的配列を説明していたことになります。
動的配列とは
箱の数(配列の要素数)が決まっていないときに使う配列のことです。
Excel VBAの場合、配列の要素数を変更するときは「配列の要素数(インデックスの範囲)を○○に変えます」という宣言が必要です。
これが配列を難しくしてしまう原因の1つだと思います。
コードの書き方は以下のとおりです。
Sub プロシージャ名() '配列の変数をインデックスの範囲を指定せずに宣言する Dim 配列名() As データ型 'ReDim Preserveステートメント を使ってインデックスの範囲を宣言しなおす ReDim Preserve 配列名(インデックスの範囲) '配列に値を格納する 配列名(インデックス) = 配列に追加したい要素 '配列に要素を増やしたいときは、もう一度ReDim Preserveステートメント を使ってインデックスの範囲を宣言しなおす ReDim Preserve 配列名(インデックスの範囲) 配列名(インデックス) = 配列に追加したい要素 End Sub
もしもReDim Preserveステートメントを使わずに配列の要素数を変えようとすると、以下のエラーが出ます。
実行時エラー'9': インデックスが有効範囲にありません。
動的配列を扱うときは、必ずReDim Preserveステートメントを使いましょう。
では、動的配列について、例を上げて説明します。
1次元配列の動的配列
たとえば、「Juice」という値を配列に追加したい場合、以下の図のように箱をもう1つ用意する必要があります。
1次元配列の動的配列の場合は、注意点は2つです。
- 配列の変数を宣言するときに、インデックスの範囲を指定しない
- ReDim Preserveステートメントを使って、インデックスの範囲を指定する
これをふまえて、配列に「Juice」を追加するコードを書きます。
Sub array2_1() Dim drinks() As String ReDim Preserve drinks(2) drinks(0) = "Coffee" drinks(1) = "Tea" drinks(2) = "Milk" ReDim Preserve drinks(3) drinks(3) = "Juice" End Sub
ローカルウィンドウで結果を見ると、「drinks(3)」 に「Juice」が入っていますね。配列の要素数を増やすことに成功しました。
2次元配列の動的配列
基本的には1次元配列の動的配列と同じです。 ReDim Preserveステートメントを使って配列の要素数を変更します。 ただし、ReDim Preserveステートメントを使って変更できるのは「配列の最後の次元のみ」ということに注意が必要です。
2次元配列の動的配列の場合は、1次元配列の注意点に加えて以下を注意してください。
- 配列の要素数を変更できるのは2次元目のみ
では、「Orange Juice」と「Apple Juice」という値を配列に追加します。
Sub array1_6() Dim drinks() As String ReDim Preserve drinks(1, 2) drinks(0, 0) = "American Coffee" drinks(0, 1) = "Earl Grey Tea" drinks(0, 2) = "Almond Milk" drinks(1, 0) = "Blended Coffee" drinks(1, 1) = "Ceylon Tea" drinks(1, 2) = "Soy Milk" ReDim Preserve drinks(1, 3) drinks(0, 3) = "Orange Juice" drinks(1, 3) = "Apple Juice" End Sub
こちらもローカルウィンドウで結果を見ると、意図したとおりに配列に要素が追加できました。
さて・・・ここで気になるのは、「2次元配列で1次元目の要素数を変えたいときはどうするのか」ということですよね。
実は、もう1つ配列を作って処理を行う必要があります。 ここもExcel VBAの配列がわかりにくい要素の1つです。
少しお話すると、TRANSPOSE関数を使って配列の次元を交換します。詳しくは、「セルを使った2次元配列の動的配列のコードの書き方」を説明する際に書きますので、しばらくお待ちください。
さいごに
配列の種類の説明はここで終わりです。動的配列を宣言するときにひと手間あるので注意が必要ですね。
次回以降からはExcelファイルのセルを使ったコードの書き方を説明します。
Excel VBAの配列にはどんな種類があるのか - 多次元配列 -
はじめに
前回は、1次元配列について説明しました。
今回は予告どおり、多次元配列について説明します。
◆目次◆
多次元配列とは
たとえば2次元配列であれば、縦と横に並べた箱の集合体、3次元配列であれば、さらに奥行きがある箱の集合体を想像してください。
この図のように、それぞれの箱にはインデックスが割り振られています。
2次元配列の場合は、左から縦向き、横向きのインデックスを指します。
3次元配列の場合は、左から奥行き、縦向き、横向きのインデックスを指します。
Excelは行と列で構成されています。 2次元配列は行と列の値を格納できるので、Excel VBAで使用すると便利です。
2次元配列のコードの書き方は1次元配列と同じです。 配列の変数を宣言し、値を入れます。
では、6つの箱にそれぞれの値を入れて、配列を作りましょう。
- インデックス0,0:American Coffee
- インデックス0,1:Earl Grey Tea
- インデックス0,2:Almond Milk
- インデックス1,0:Blended Coffee
- インデックス1,1:Ceylon Tea
- インデックス1,2:Soy Milk
それぞれの箱に値を入れました。この配列をコードで書くと以下のとおりです。
Sub array1_3() Dim drinks(1, 2) As String drinks(0, 0) = "American Coffee" drinks(0, 1) = "Earl Grey Tea" drinks(0, 2) = "Almond Milk" drinks(1, 0) = "Blended Coffee" drinks(1, 1) = "Ceylon Tea" drinks(1, 2) = "Soy Milk" End Sub
もちろん、インデックスの開始位置を0以外にすることも可能です。
たとえば、インデックスを「1,1」から開始する場合、以下のコードになります。
Sub array1_4() Dim drinks(1 To 2, 1 To 3) As String drinks(1, 1) = "American Coffee" drinks(1, 2) = "Earl Grey Tea" drinks(1, 3) = "Almond Milk" drinks(2, 1) = "Blended Coffee" drinks(2, 2) = "Ceylon Tea" drinks(2, 3) = "Soy Milk" End Sub
図にすると、インデックスがExcelのセルのように見えませんか。何回か後の記事で、実際にセルの値を使った配列のコードの書き方も説明しますので、しばらくお待ちください。
さいごに
いかがでしたか。多次元配列になると、さまざまな方向に値の格納ができるようになりました。
次回は静的配列と動的配列について説明します。