Office関連

「IEを自在に操る Excel VBAプログラミング入門」レビュー

※ 下記レビューはあくまでも個人的な感想です。

2013年9月27日に発売された「IEを自在に操るExcel VBA(ブイビーエー)プログラミング入門―データの収集・加工を完全自動化!」を早速購入してきました。

作者はC# MVPの増田智明氏、池谷京子氏、厂崎敬一郎氏の三名で、概要とサンプルコードは下記ページから見ることができます。

・IEを自在に操る Excel VBAプログラミング入門|書籍情報|秀和システム
http://www.shuwasystem.co.jp/products/7980html/3915.html
・IEを自在に操る Excel VBAプログラミング入門|サポート|秀和システム
http://www.shuwasystem.co.jp/support/7980html/3915.html

本書ではVBAマクロでInternet Explorer操作し、Web上のデータの収集・加工を自動化する、所謂「ウェブスクレイピング」手法について解説しています。
上記書籍情報ページにある目次を見れば分かる通り、本書ではChapter 1.から3.まででVBAの基本的な情報を、Chapter 4.以降でIEを操作する方法やWeb APIを使って情報を取得する方法などを解説しています。

本書を読んでまず私が思ったことは、“本書は幅広い内容を取り扱っていて、実践的で面白い”ということです。
本のタイトル通り、VBAマクロでネット上の情報を収集する方法が主題になってはいるのですが、Chapter 11.ではF#でマネージDLLを作成し、それをVBAから呼び出す手法まで解説されています。
VBAの解説本でここまで書かれている書籍を私は本書以外に知りません。

主題であるネット上の情報を収集する方法も実践的で、たとえば、特定の情報だけを取得するために画像のalt属性の値で判断する方法、API関数のURLDownloadToFileDeleteUrlCacheEntryの使い方、VBAマクロからのWeb APIの利用方法などが解説されているので、本書を見ればすぐにでも実際のWebページから情報を取得できるようになるだろうと思います。

同様のテーマについて取り扱っている「Excel VBAでIEを思いのままに操作できるプログラミング術」と比べると、こちらはよりVBA初心者に近く、本書はそれよりも難易度が高く、中級者向けになるのではないかと思います。

ただ、どちらの書籍に対しても私が気になるのは、“ウェブスクレイピングの利点については触れられていても危険性についてはあまり触れられていない”点です。
この記事でも書いていますが、ウェブスクレイピングは必ずしも安全でリスクの無い技術とは言えません。
一般的にはWebサービス提供者からあまり歓迎されておらず、TwitterJARTICのように明示的にウェブスクレイピングを禁止しているサイトも少なくありません。

(iii) Twitterから提供されている当社の現在利用可能な公開インターフェースを経由する(かつ、その使用条件に従う)ことなく、その他の何らかの手段(自動その他を問わず)で本サービスへのアクセスもしくはその検索を行うか、またはアクセスもしくは検索を試みること。ただし、Twitterと別途締結した契約によりこれを行うことが特に認められている場合はこの限りではありません。(注:本サービスのクローリングは、robots.txtファイルの定めによる場合には許されます。ただし、Twitterの事前の承諾なしに本サービスのスクレイピングを行うことは明示的に禁じられています)。

Twitter / サービス利用規約 より

禁止事項について
当サイトの内容の全部または一部について、情報センターの許可なく、以下の事項を行うことはできません。
(中略)
当サイト内容の改変、変更、他のウェブサイト・ウェブページ・ソフトウェア (アプリケーション) 上における、ミラーサイトの作成・スクレイピング・フレーム表示を行うこと

ご利用上の注意(サイトご利用規定) [JARTICインフォメーション] 公益財団法人日本道路交通情報センター JARTIC より

本書で取り扱っている「@cosme」も免責事項・コピーライトに下記のような記述があり、ウェブスクレイピングが許可されているのかどうかは非常に微妙なところです。

@cosmeのクチコミ等のデータを当社の許可する方法以外で@cosme上から収集し、分析を行なうこと、また、その結果を公開するなどの行為を禁じます。(営利・非営利を問わず)

免責事項・コピーライト より

——— 2013/9/30 追記開始 ——————–
お問い合わせフォームがあったので、試しに「@cosme」の担当の方に、プログラムを使って自動的に情報を取得するウェブスクレイピング行為が許可されているのかどうかを聞いてみました。

免責事項に記載をさせていただいておりますとおり、
@cosmeサイト上に掲載されている情報を利用することについては、
いかなる方法においてもご遠慮いただいております。ご了承ください。

なお別途、弊社とお取引などを頂いた上でご利用いただく場合には、
以下に担当の窓口を設けておりますので、
お手数ですが、あらためてご連絡をいただけますと幸いです。

●株式会社アイスタイル メディア事業
http://www.istyle.co.jp/business/media/

※お問い合せ:https://www.istyle.co.jp/contact-entry/form.php

上記がその回答になりますが、これを見る限り@cosmeのサイトに対するスクレイピング行為は許可されていないようです。
——— 2013/9/30 追記終了 ——————–

本書にも記載されている通り、サイトに大きな負担をかけないようにするというのはもちろんですが、事前にウェブスクレイピングが禁止されていないかどうかを確認する、上で挙げたTwitterのように、APIが公開されているのであればそちらを使う、といったことも必要ではないかと、個人的には思います。
(本書も、“サイトに大きな負担をかけないように注意する”という一文を書いているのであれば、具体的にどのようにするのか、コード例があればより親切だったと思います。)

他に気になったところとしては、Sleep関数の説明部分で“32ビット版のExcelと64ビット版のExcelを区別するのにVBA7キーワードを使う”とあったのですが、VBA7は文字通りVBAのバージョンを区別するためのものなので、正確に区別するためには「Win64」条件付きコンパイル定数を使った方が良いのではないかと思いました。
(これは個人的な好みの部分もあるだろうと思いますが・・・。)

また、これは著者が複数であるためだと思いますが、API関数の宣言が、とあるChapterでは32ビット版向けで書かれていても、別のChapterでは64ビット版向けになっていたりと、統一されていない点が気になりました。
(ついでに、p.261で「64ビット版のExcelを使っている場合は、PtrSafeキーワードを外して使ってください」と書かれているのは「32ビット版」の誤植ですね。)

などと非常に細かい点が目についてしまいましたが、上でも書いた通り、本書はVBAの基本から、IEの操作方法、Web APIの利用方法、マネージDLLの作成・登録・利用方法まで書かれていて、とても読み応えがあって面白いです。

Excel VBAでIEを思いのままに操作できるプログラミング術」と本書をじっくり読めば、VBAマクロによるウェブスクレイピング手法についてかなり深く知ることができるのではないでしょうか。

最後にもう一つツッコミを。
書籍情報ページにある、

対象読者:初級

VSでF# DLLまで作らせといて、逆引き大全の「中級」以下かい!?
どないなっとんねん!!??

コメント

    • maruwo
    • 2013年 9月 29日

    私はwindows8のuserです。
    windows7の時は[Fn]キーを押さずF8キーを押せてとてもべんりでした、、、
    どなたかwindows8の[Fn]キーを使わずにF8を押せる方法を教えて頂きませんか??

    • sui
    • 2014年 3月 06日

    詳しくありがとうございます!

    ところで、この書籍には普通に書いてあるのですが、
    getElementsByClassNameがうまく作動しません。

    ステップ・インではうまく作動しても普通に作動するとできない。
    Win8、IE11ですけどなにかうまいやり方があるのでしょうか?

    具体的にはこちらのコードです。

    Public Sub IE基本_郵便検索2()
    ‘ 新しいIEを開く
    Dim ie As New InternetExplorer
    ie.Navigate “http://www.post.japanpost.jp/zipcode/”
    ie.Visible = True
    ‘ 完了待ちをする
    While ie.Busy = True And ie.ReadyState < READYSTATE_COMPLETE
    DoEvents
    Wend
    Dim doc As HTMLDocument
    Set doc = ie.Document
    Dim sel As IHTMLSelectElement
    Dim inp As IHTMLInputElement

    ' 都道府県を設定
    Set sel = doc.getElementsByName("pref")(0)
    sel.Value = 13 ' 東京都
    ' 市区町村を設定
    Set inp = doc.getElementsByName("addr")(0)
    inp.Value = "板橋区常盤台"
    ' 「郵便番号を検索」ボタンを押す
    Dim btn As IHTMLInputElement
    Set btn = doc.getElementsByTagName("input")(9)
    btn.form.submit
    ' 完了待ちをする
    While ie.Busy = True And ie.ReadyState 0 Then
    Exit Do
    End If
    DoEvents
    Loop
    Dim url As String
    Dim i
    For i = 1 To coll.Length
    Dim el As IHTMLElement2
    Set el = coll(i – 1)
    If el.tagName = “DIV” Then
    Dim ela As IHTMLAnchorElement
    Set ela = el.getElementsByTagName(“a”)(0)
    url = ela.href
    Exit For
    End If
    Next
    ie.Navigate2 url, &H800
    End Sub

    よろしければ教えていただけると嬉しいです(^_^;)

  1. > sui様

    コードの一部にエラーになる部分があったので勝手に修正させていただきました。

    Option Explicit
    
    Public Sub IE基本_郵便検索2()
        '新しいIEを開く
        Dim ie As New InternetExplorer
        
        ie.Navigate "http://www.post.japanpost.jp/zipcode/"
        ie.Visible = True
        
        '完了待ちをする
        While ie.Busy = True And ie.ReadyState < READYSTATE_COMPLETE
            DoEvents
        Wend
        
        Dim doc As HTMLDocument
        Dim sel As IHTMLSelectElement
        Dim inp As IHTMLInputElement
        
        Set doc = ie.Document
        
        ' 都道府県を設定
        Set sel = doc.getElementsByName("pref")(0)
        sel.Value = 13    ' 東京都
        
        ' 市区町村を設定
        Set inp = doc.getElementsByName("addr")(0)
        inp.Value = "板橋区常盤台"
        
        ' 「郵便番号を検索」ボタンを押す
        Dim btn As IHTMLInputElement
        Set btn = doc.getElementsByTagName("input")(9)
        btn.form.submit
        
        ' 完了待ちをする '修正
        'While ie.Busy = True And ie.ReadyState 0 Then
        '    Exit Do
        'End If
        'DoEvents
        'Loop
        While ie.Busy = True And ie.ReadyState < READYSTATE_COMPLETE
            DoEvents
        Wend
    
        Dim url As String
        Dim i
        Dim el As IHTMLElement2
        Dim ela As IHTMLAnchorElement
        Dim coll As IHTMLElementCollection '追加
        
        Set coll = doc.all '追加
        For i = 1 To coll.Length
            Set el = coll(i - 1) '修正
            If el.tagName = "DIV" Then
                Set ela = el.getElementsByTagName("a")(0)
                url = ela.href
                Exit For
            End If
        Next
        
        ie.Navigate2 url, &H800
    End Sub

    このコードを見ると、問題であるgetElementsByClassName関数は使われていないようですが、具体的にどう上手く動作しないのでしょうか?

    • sui
    • 2014年 3月 06日

    すみません、コードの写し間違いだったようです(汗)

    こちらのコードになります。
    Public Sub IE基本_郵便検索2()
    ‘ 新しいIEを開く
    Dim ie As New InternetExplorer
    ie.Navigate “http://www.post.japanpost.jp/zipcode/”
    ie.Visible = True
    ‘ 完了待ちをする
    While ie.Busy = True And ie.ReadyState < READYSTATE_COMPLETE
    DoEvents
    Wend
    Dim doc As HTMLDocument
    Set doc = ie.Document
    Dim sel As IHTMLSelectElement
    Dim inp As IHTMLInputElement

    ' 都道府県を設定
    Set sel = doc.getElementsByName("pref")(0)
    sel.Value = 13 ' 東京都
    ' 市区町村を設定
    Set inp = doc.getElementsByName("addr")(0)
    inp.Value = "板橋区常盤台"
    ' 「郵便番号を検索」ボタンを押す
    Dim btn As IHTMLInputElement
    Set btn = doc.getElementsByTagName("input")(9)
    btn.form.submit
    ' 完了待ちをする
    While ie.Busy = True And ie.ReadyState 0 Then
    Exit Do
    End If
    DoEvents
    Loop
    Dim url As String
    Dim i
    For i = 1 To coll.Length
    Dim el As IHTMLElement2
    Set el = coll(i – 1)
    If el.tagName = “DIV” Then
    Dim ela As IHTMLAnchorElement
    Set ela = el.getElementsByTagName(“a”)(0)
    url = ela.href
    Exit For
    End If
    Next
    ie.Navigate2 url, &H800
    End Sub

    • sui
    • 2014年 3月 06日

    すみませんやり直しです。

    Public Sub IE基本_郵便検索2()
    ‘ 新しいIEを開く
    Dim ie As New InternetExplorer
    ie.Navigate “http://www.post.japanpost.jp/zipcode/”
    ie.Visible = True
    ‘ 完了待ちをする
    While ie.Busy = True And ie.ReadyState < READYSTATE_COMPLETE
    DoEvents
    Wend
    Dim doc As HTMLDocument
    Set doc = ie.Document
    Dim sel As IHTMLSelectElement
    Dim inp As IHTMLInputElement

    ' 都道府県を設定
    Set sel = doc.getElementsByName("pref")(0)
    sel.Value = 13 ' 東京都
    ' 市区町村を設定
    Set inp = doc.getElementsByName("addr")(0)
    inp.Value = "板橋区常盤台"
    ' 「郵便番号を検索」ボタンを押す
    Dim btn As IHTMLInputElement
    Set btn = doc.getElementsByTagName("input")(9)
    btn.form.submit
    ' 完了待ちをする
    While ie.Busy = True And ie.ReadyState 0 Then
    Exit Do
    End If
    DoEvents
    Loop
    Dim url As String
    Dim i
    For i = 1 To coll.Length
    Dim el As IHTMLElement2
    Set el = coll(i – 1)
    If el.tagName = “DIV” Then
    Dim ela As IHTMLAnchorElement
    Set ela = el.getElementsByTagName(“a”)(0)
    url = ela.href
    Exit For
    End If
    Next
    ie.Navigate2 url, &H800
    End Sub

    • sui
    • 2014年 3月 06日

    ??
    コメント投稿すると該当部分だけなぜか消えますね(・・;

    少しテストします。

    ‘この部分です!
    Do
    Set coll = doc.getElementsByClassName(“data”)
    If coll.Length > 0 Then
    Exit Do
    End If
    DoEvents
    Loop

    • sui
    • 2014年 3月 06日

    コメントが多重化してしまいすみません。
    今度こそ…
    Public Sub IE基本_郵便検索2()
    ‘ 新しいIEを開く
    Dim ie As New InternetExplorer
    ie.Navigate “http://www.post.japanpost.jp/zipcode/”
    ie.Visible = True
    ‘ 完了待ちをする
    While ie.Busy = True And ie.ReadyState < READYSTATE_COMPLETE
    DoEvents
    Wend
    Dim doc As HTMLDocument
    Set doc = ie.Document
    Dim sel As IHTMLSelectElement
    Dim inp As IHTMLInputElement

    ' 都道府県を設定
    Set sel = doc.getElementsByName("pref")(0)
    sel.Value = 13 ' 東京都
    ' 市区町村を設定
    Set inp = doc.getElementsByName("addr")(0)
    inp.Value = "板橋区常盤台"
    ' 「郵便番号を検索」ボタンを押す
    Dim btn As IHTMLInputElement
    Set btn = doc.getElementsByTagName("input")(9)
    btn.form.submit
    ' 完了待ちをする
    While ie.Busy = True And ie.ReadyState 0 Then
    Exit Do
    End If
    DoEvents
    Loop
    Dim url As String
    Dim i
    For i = 1 To coll.Length
    Dim el As IHTMLElement2
    Set el = coll(i – 1)
    If el.tagName = “DIV” Then
    Dim ela As IHTMLAnchorElement
    Set ela = el.getElementsByTagName(“a”)(0)
    url = ela.href
    Exit For
    End If
    Next
    ie.Navigate2 url, &H800
    End Sub

    • sui
    • 2014年 3月 06日

    やっぱり消えるみたいです(泣)
    なぜでしょう。。。

    聞きたいのは、
    本書のサンプルである秀和の4-3の部分です。
    http://www.shuwasystem.co.jp/support/7980html/3915.html

    ↓ここの部分が、うまく作動しません。
    ステップインだとうまくいきますが、連続実行だとうまく動かない。
    Set coll = doc.getElementsByClassName(“data”)
    If coll.Length > 0 Then

    ブレイクポイントで止めてみると、coll.Lengthが0のままになっていることが
    判明しました。
    ステップインだとここが2になるのですが……。

    この理由がよくわからなくて困っていますorz
    ご助言いただけると大変助かります!

    • > sui様

      Windows 8 + IE10、Windows 8.1 + IE11環境で4-6のコードを動かしてみましたが、私の環境では再現できませんでした。
      そのため、どこに原因があるのか検証できなかったのですが、IEのバージョンによっては下記Webページのような問題もあるため、

      ・Web Tableのコピーでエラー
      http://www.moug.net/faq/viewtopic.php?t=67419

      該当のページを互換表示設定( http://support.microsoft.com/kb/2618122/ja )に追加してテストしてみてはいかがでしょうか。

        • sui
        • 2014年 3月 07日

        きぬあさ様

        ありがとうございます!
        私もWin8.1で同じ環境でした。

        互換についてはすでに試していましたが、URL追加はしていなかったので
        試したのですが、やっぱりうまく動きませんね。

        処理前にSLEEPなどを入れてみましたが駄目でした(^_^;)

        あまりに原因がわからないので、
        発行元に直接メール飛ばしてみました(^^)

        • > sui様

          Windows 7 + IE9でも試してみましたが、結果は変わらず問題を再現することができませんでした。
          大変申し訳ないのですが、私の方では問題の原因を突き止めることができなさそうです。
          発行元からの返信で解決されると良いですね!

  1. この記事へのトラックバックはありません。

Time limit is exhausted. Please reload CAPTCHA.

おすすめ記事

アーカイブ

RapidSSL_SEAL-90x50
PAGE TOP