質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

2回答

2069閲覧

VBA スクレイピングプログラムのエラー

blacksanta

総合スコア23

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2018/09/25 15:31

編集2018/09/29 05:51

VBAでスクレイピングプログラムを作成したのですが、
100サイトくらいスクレイピングを行うとエラーが発生します。
50サイトづつに分けると問題なくプログラムが最後まで動きます。
原因、改善方法がわかる方アドバイス頂ければ有り難いです。

イメージ説明

イメージ説明

VBA

1Private Function a(btAry As String) 2 3 Application.ScreenUpdating = False 4 5 Dim i As Long 6 Dim urlLen As Long 7 Dim urlStr() As String 8 Dim tAry() As String 9 10 urlStr() = Split(btAry, ",") 11 urlLen = UBound(urlStr) 12 13 14 ReDim tAry(urlLen, 1) As String 15 16 For i = 0 To urlLen - 1 17 tAry(i, 0) = urlStr(i) 18 sleep (1) 19 Next 20 21 Dim ie As InternetExplorer 22 Dim htdoc As HTMLDocument 23 Dim tagName As HTMLElementCollection 24 25 Set ie = CreateObject("InternetExplorer.Application") 26 27 ie.Visible = True 28 ie.Top = True 29 ie.Left = True 30 ie.Width = 500 31 ie.Height = 500 32 33 For i = 0 To urlLen - 1 34 Debug.Print i & " / " & urlLen - 1 35 ie.Navigate tAry(i, 0) 36 37 Do While ie.Busy Or ie.ReadyState < READYSTATE_COMPLETE 38 DoEvents 39 Loop 40 41 Set htdoc = ie.Docum 42 ent 43 44 45 If InStr(htdoc.URL, "") > 0 Then 46 For Each tagName In htdoc.getElementsByClassName("") 47 If InStr(tagName.outerText, "") > 0 Then 48 tAry(i, 1) = "×" 49 Exit For 50 End If 51 Next 52 End If 53 54 55 Set htdoc = Nothing 56 Set tagName = Nothing 57 sleep 1 58 Next 59 60 ie.Quit 61 62 Set ie = Nothing 63 Set htdoc = Nothing 64 65 Dim num As Long 66 Dim ws As Worksheet 67 Set ws = ActiveSheet 68 num = ws.Cells(1, 1).CurrentRegion.Rows.Count - 1 69 70 For i = 0 To num - 2 71 If ws.Cells(i + 2, 1).value = tAry(i, 0) Then 72 ws.Cells(i + 2, 3).value = tAry(i, 1) 73 End If 74 sleep 1 75 Next 76 77 Set ws = Nothing 78 79End Function

イメージ説明

何回か試して見ると別のエラーもでました。

↓tagNameはこちらで定義しています。
Dim tagName As HTMLElementCollection

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

h.horikoshi

2018/09/26 05:28

【依頼】保護モードを確認してみてください。→エラーの発生した時点で、IEには問題となったWebページが表示されていると思いますが、そのページ上で、右クリック→プロパティと操作。→「ゾーン」の行はどのような値になっていますか? 保護モード=「有効」ならOKですが、「無効」だと問題ありかもです。
blacksanta

2018/09/29 04:21

保護モードは「有効」になっていました。
h.horikoshi

2018/10/02 00:32

確認ありがとうございました。"有効"ならば問題なさそうですね。 ※私の経験ですが、 以前、Navigationまではできるのにその後の操作ができない。という状況になり、 そのときは、保護モードとIEオブジェクト InternetExplorer.Application or InternetExplorer.ApplicationMedium の組み合わせが原因でしたので。
guest

回答2

0

100サイトくらいスクレイピングを行うとエラーが発生します。
50サイトづつに分けると問題なくプログラムが最後まで動きます。

コードは読んでいませんが、単純に考えられるのはメモリリークとかでしょうか。
例えば30回毎にieオブジェクトを破棄して、改めてCreateObjectするようにしたら改善するかもしれません。

VBA

1Private Function urlscr(btAry As String) 2 3 Application.ScreenUpdating = False 4 5 Dim i As Long 6 Dim urlLen As Long 7 Dim urlStr() As String 8 Dim tAry() As String 9 10 urlStr() = Split(btAry, ",") 11 urlLen = UBound(urlStr) 12 13 ReDim tAry(urlLen, 1) As String 14 15 For i = 0 To urlLen - 1 16 tAry(i, 0) = urlStr(i) 17 Sleep (1) 18 Next 19 20 Dim ie As InternetExplorer 21 Dim htdoc As HTMLDocument 22 Dim tagName As HTMLElementCollection 23 24'変更箇所 ここから 25 Const ResetPages = 30 26 27 For i = 0 To urlLen - 1 28 If i Mod ResetPages = 0 Then 29 If Not ie Is Nothing Then 30 ie.Quit 31 End If 32 33 Set ie = CreateObject("InternetExplorer.Application") 34 35 ie.Visible = True 36 ie.Top = True 37 ie.Left = True 38 ie.Width = 500 39 ie.Height = 500 40 End If 41'変更箇所 ここまで 42 43 Debug.Print i & " / " & urlLen - 1 44 ie.Navigate tAry(i, 0) 45 46 Do While ie.Busy Or ie.ReadyState < READYSTATE_COMPLETE 47 DoEvents 48 Loop 49 50 Set htdoc = ie.document 51 52 If InStr(htdoc.Url, "") > 0 Then 53 For Each tagName In htdoc.getElementsByClassName("") 54 If InStr(tagName.outerText, "") > 0 Then 55 tAry(i, 1) = "×" 56 Exit For 57 End If 58 Next 59 End If 60 61 62 Set htdoc = Nothing 63 Set tagName = Nothing 64 Sleep 1 65 Next 66 67 ie.Quit 68 69 Set ie = Nothing 70 Set htdoc = Nothing 71 72 Dim num As Long 73 Dim ws As Worksheet 74 Set ws = ActiveSheet 75 num = ws.Cells(1, 1).CurrentRegion.Rows.Count - 1 76 77 For i = 0 To num - 2 78 If ws.Cells(i + 2, 1).Value = tAry(i, 0) Then 79 ws.Cells(i + 2, 3).Value = tAry(i, 1) 80 End If 81 Sleep 1 82 Next 83 84 Set ws = Nothing 85 86End Function

それと、100サイト回した時に、何回目くらいでエラーが出るのか、エラーが出たサイトを序盤に実行した場合に同じサイトでエラーにならないか。
といった法則性について調査されていないので調べてみたほうが良いかもしれません。

投稿2018/09/26 01:23

編集2018/09/30 08:29
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

blacksanta

2018/09/29 05:45

ありがとうございます! 何回目でエラーが出るか、エラーが出るサイトは毎回変わりました。 一度エラーが出たサイトでももう一回VBAを実行するとエラーなくスクレイピングできたりします。 エラーが出たサイトを序盤に実行した場合も同じサイトでエラーにならなかったです。
退会済みユーザー

退会済みユーザー

2018/09/30 08:31

肝心のieを再起動する部分を試していただけてないようなので、サンプルコードを追記しました。ご確認ください。 本当はエラーが出る回数が定かではないので、エラーをハンドルしたら再起動というコードも考えたんですけど流れが複雑になりそうなので、とりあえず30回でieを再起動する例です。
guest

0

ベストアンサー

IE11でしょうか。
待ち時間処理を工夫することで
症状が緩和する可能性があります。
よろしければ試してみてください。

Do While ie.Busy Or ie.ReadyState < READYSTATE_COMPLETE DoEvents: Sleep 200 '200ms停止 Loop DoEvents Do While ie.Busy or ie.document.readyState <> "complete" DoEvents: Sleep 200 '200ms停止 Loop

投稿2018/09/30 07:54

TanakaHiroaki

総合スコア1063

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問