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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

4回答

11941閲覧

webBrowserオブジェクトで何度も繰り返しNevigateをしていると、エラーになってしまうのを防ぐ方法は無いものでしょうか?

GiveAHand

総合スコア286

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2016/07/26 05:57

C#のwebBrowserオブジェクトを使って、HTMLのスクレイピングをするプログラムを作成しています。

NavigateメソッドでURLを指定して、DocumentCompletedで取得したHTMLをスクレイピングするという流れなのですが、だいたい50件以上になると、何かしらエラーになってしまいます。

ただ繰り返しているだけなのに、何が原因かはわかりません。

起きるエラーは、

(1)メモリ不足 (2)Widndowsに問題を送信 (3)エラーもなくそのまま処理が完了しない

の3パターンです。

プログラムの作りとしましては、

C#

1webBrowser.Navigated(URL);

このようにNavigateメソッドでURLを指定して、

C#

1private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e){ 2 3 HtmlElementCollection htmldata = webBrowser.Document.All; 4 5 // 取得したHTMLを使って、スクレイピング処理を行う 6{

このような感じで、HTMLを取得して、スクレイピングを行っています。

この処理を、foreachで繰り返しているのですが、このような作りでは、回数を重ねるとエラーになってしまうものなのでしょうか?

一般的に、大量のURLのスクレイピングを行う場合、何か注意しなければならないことなどは無いでしょうか?

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

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

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

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

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

guest

回答4

0

WebBrowser から取得できる Document やそこから取得できるオブジェクトは COM オブジェクトと呼ばれるもので、C# のコード(.NET)から扱うには常にこれを意識しましょう。

Chironian さんの回答に補足ですがこのような COM オブジェクトの開放には特に注意が要ります。開放している途中で例外が発生することを考慮すると常に次のようなコーディングが必要になります。

また、COM オブジェクトをクラスのフィールドやプロパティに持つなどして参照を保持していないかも確認してください。

lang

1HtmlDocument document = null; 2try 3{ 4 // COM オブジェクト 5 document = webBrowser.Document; 6 7 HtmlElementCollection all = null; 8 try 9 { 10 // COM オブジェクト 11 all = document.All; 12 13 HtmlElement element = null; 14 try 15 { 16 // COM オブジェクト 17 element = all["name"]; 18 } 19 finally 20 { 21 // 解放処理 22 if (element != null) 23 { 24 Marshal.FinalReleaseComObject(element); 25 } 26 } 27 } 28 finally 29 { 30 // 解放処理 31 if (all != null) 32 { 33 Marshal.FinalReleaseComObject(all); 34 } 35 } 36} 37finally 38{ 39 // 解放処理 40 if (document != null) 41 { 42 Marshal.FinalReleaseComObject(document); 43 } 44}

非常に面倒くさいので COM 用にラッパークラスを作って using で解放できるようなものを作ると少しマシになります。

投稿2016/07/29 16:17

chitoku

総合スコア1610

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

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

GiveAHand

2016/11/12 01:12

chitoku様 お返事が遅くなりまして、すみません。 なるほど。 そうなんですね。 いろいろバタバタしまして、バグはそのままなんですが、 大変勉強になりました。 ありがとうございました。m(_ _)m
guest

0

少し古い情報ですが、「[.NET] WebBrowserをDisposeしても、メモリが開放されない件について」などによると WebBrowser には COM が解放されないバグが長年修正されず放置されているようです。このバグはマイクロソフトも知っていますが、修正されたという情報は聞きません。(私が聞いてないだけかもしれません)

したがって、WebBrowser ではなく別の方法でスクレイピングしてはどうでしょうか? HTML Agility Pack や libcurl for .NET またはサードパーティーのライブラリを入れないなら HttpClient をお勧めします。

投稿2016/07/29 16:00

Zuishin

総合スコア28656

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

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

Zuishin

2016/07/29 16:02

最近同じような質問に答えた記憶があると思ったら同じ人でしたね。無視してください。
GiveAHand

2016/11/12 01:08

Zuishin様 お返事が遅くなりまして、すみません。 貴重な情報をありがとうございました。 結局のところ、バグは直さず、 回数が多いときはまめにPCをシャットダウンする事に致しました。
guest

0

ベストアンサー

こんにちは。

そのような時はリソース・リークが疑わしいです。
ファイルを開いた後明示的にはクローズしていないみたいな操作です。

C# リソースの種類と解放の必要性に概要がありました。

投稿2016/07/26 06:49

Chironian

総合スコア23272

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

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

GiveAHand

2016/07/26 08:09

Chironian様 情報ありがとうございます。 ただ、Dipsoseなど、メモリ解放の処理をしてみましたが、あまり効果はありませんでした。。。
Chironian

2016/07/26 08:21

他にもまだ開放できていないリソースが残っているということはないでしょうか? webBrowserを次々とnewしているというようなこともないでしょうか? webBrowser_DocumentCompleted()の中身を空にしてみても発生するようでしたら、navigate()側に何か残っている筈です。発生しなくなればwebBrowser_DocumentCompleted()の中身に何かあるはずです。
GiveAHand

2016/11/12 00:54

Chironian様 お返事が遅くなりましてすみません。 いろいろ調べたのですが、これはどうもIEのエラーのようで、 PCを再起動せずに約100回ほどIEの再起動を繰り返すと、メモリ不足によるエラーになるようです。 (回数などはPCのスペックなどにより異なるかもしれません。) いろいろと、ありがとうございました。
guest

0

そういうときは、エラーが起こるものとしてWebBrowserコントロールを含むクローラー自体を
別プログラムに切り離しましょう。

投稿2018/05/24 04:27

tekka

総合スコア514

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問