c#によるIE自動操作のサンプルコード(初心者向け)

副業でネットビジネスに取り組んでいるぱーくんと申します。
激務でも増えない給料に失望し、将来のために別の収入源が欲しい!の一心でネットビジネスをはじめ、2018年4月に20万円達成。
ひと月36万アクセスあるサイトを作ったノウハウは無料で公開中。 ⇒⇒コチラ
ネットビジネスで未来を夢見れる方を一人でも増やしたいと思っています。
誰でも最初は初心者。
【やってみたいけど、初心者だから不安】
という方は、ぜひお気軽にお問合せください♪
IEを自動制御するC#のアプリケーションを作成してみましょう。
ブラウザを自動で操作するにはSeleniumという仕組みも使えますが、今回はCOMを使った操作を行います。
COMというと少し難しく聞こえますが、要は特別な仕組みでなく、Windowsの機能のみで作ってしまおうということです。
ExcelなどのVBAマクロでもほぼ同じようなやり方で出来ると思います。
サンプルとして作るのは以下のようなアプリです。
- 検索したいキーワードを入力してボタンを押すと、自動でInternet Explorer(ブラウザ)が起動する。
- ブラウザでは入力したキーワードで検索される。
- 結果が表示されたら5秒後に自動でブラウザが閉じる。
もくじ
プロジェクトを作成
はじめにプロジェクトを作成します。
フリーの開発環境Microsoft Visual Studio 2019を使います。
「新しいプロジェクトの作成」⇒「Windowsフォームアプリケーション」を選択します。
プロジェクトを作成すると、下記のようなフォームが表示されるので、
TextBoxとButtonを配置します。
ブラウザを自動で開いてサイトを表示するソースと設定が必要な参照
シンプルにブラウザを開いて、指定したサイトを表示させるには、以下のコードでOKです。
ブラウザを操作するハンドラ(インスタンス)を以下のように宣言し、Navigate()するだけです。
1 2 3 | SHDocVw.InternetExplorer objIE = new SHDocVw.InternetExplorer(); //オブジェクトを作成 objIE.Navigate("about:blank"); //空ページの表示 objIE.Visible = true; //IEを表示 |
さて、このハンドラを使ってIEの自動操作していくわけですが、それにあたって、いくつか参照が必要なので以下のように追加していきます。
SHDocVwの参照追加
SHDocVwのクラスを使えるように、「参照」から「参照の追加」でCOMの「Microsoft Internet Controls」にチェックを入れ、追加します。
mshtml.HTMLDocument用の参照追加
また、Webページを表示した後、要素を取得するのに「mshtml.HTMLDocument」を使うので、COMの「Microsoft HTML Object Library」を参照に追加します。
UrlEncodeのための参照追加
System.Web.HttpUtility.UrlEncodeを使うには、アセンブリの「System.Web」を参照で追加します。
Yahooに対して検索を行うには、
https://search.yahoo.co.jp/search?b=0&p=<検索キーワード>
のようなURLを投げる必要がありますが、検索キーワードの部分が日本語などのマルチバイトの文字の場合、そのままだとエラーになります。
この場合、URLEncodeしてリクエストを投げる必要があるためです。
要素の取得の方法
さて、さっそく自動操作していきましょう。
まず、以下のようにInternetExplorerをインスタンス化します。
その後、Navigate()メソッドで、targetUrlのサイトを読み込みます。
1 2 3 | objIE = new SHDocVw.InternetExplorer(); objIE.Navigate(targetUrl); |
Navigte後、ページがロードされたら、そのロードの結果、解析されたHTML文書がDocumentに入っていますので
1 2 3 4 5 6 7 8 9 10 11 12 13 | var ObjHtml = (mshtml.HTMLDocument)objIE.Document; string gStrRes = ""; var bodys = ObjHtml.getElementsByTagName("body"); foreach (mshtml.IHTMLElement element in bodys) { if (element != null) { gStrRes = element.outerHTML; } } |
のようにすると、サイト全体をテキストで取得することができます。
objIEにはその結果が入っていますので、一度Navigateでサイトを読み込んでしまえば、あとは、その中の要素をgetElementsByXXXまたはgetElementByXXXで取得することができます。
例えば、getElementById()で要素を取得し、その内容を取得するには以下のようにします。
1 2 | mshtml.IHTMLElement elm = ObjHtml.getElementById("js-tracked_mod_1"); Debug.WriteLine("elm=" + elm.outerHTML); |
一方、getElementsByXXX という形式の関数はElementsとあるように要素が複数返ります。
body要素は1つしかないので、上記のやり方でbody要素、つまりページ全体のテキストを取得できます。
これをデバッグなどで出力すると、どんなHTMLソースが返却されたかがわかるので、
どんな要素名で取得すればいいか?
などが分かりやすいです。
注意点としては、実際に返却されるHTMLソースと、上記のソースは若干異なることがあります。
それは、返却されたHTML文書をドライバが解釈して、ツリー構造にした結果が「mshtml.IHTMLElement」だからです。
そのため、期待される要素名で取得できない場合は、デバッグで出力させてみることをお勧めします。
クラス名で要素を取得するTips
タグやIdで取得するメソッドはありますが、クラス名で取得するメソッドは存在しません。
そのため、特定のクラス名で取得したい場合は、
1 2 3 4 5 6 7 8 9 10 11 | var rankurls = ObjHtml.getElementsByTagName("a"); foreach (mshtml.IHTMLElement element in rankurls) { //Debug.WriteLine("foreach" + (String)(element.getAttribute("className"))); if ((String)(element.getAttribute("className")) == "sw-Card__titleInner") { String siteUrl = element.getAttribute("href"); Debug.WriteLine("URL=" + siteUrl); } } |
のように、タグで取得し、そのタグの要素のクラス名を指定することで取得すると良いです。
上記の例だと、aタグで取得し、その要素のクラス名が「sw-Card__titleInner」のものを抜き出しています。
すると、
<a class=”sw-Card__titleInner” href=”http://search.yahoo.co.jp/xxxxx” >南青山 <b>まめ</b></h3><br><div class=”sw-Cite”><cite>www.<b>mamemame</b>.info/</cite></div></a>
のような要素のhrefの属性が取得できるというわけです。
ページの読み込み完了まで待つ方法
ネットワークの状態によっては、すぐにレスポンスが返ってくるかわかりませんし、ページのロードに時間がかかってしまう場合もあります。
そのため、ページが全部読み込まれるまで、完了を待つようにすると良いです。
1 2 3 4 5 6 | while (objIE.Busy || objIE.ReadyState != SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE) { //無処理 System.Windows.Forms.Application.DoEvents(); System.Threading.Thread.Sleep(100); } |
サンプルソース全文
以下がサンプルソースです。
このまま貼り付けると動くも状態になっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | using System; using System.Windows.Forms; using System.Diagnostics; namespace IEAutoSample { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { SHDocVw.InternetExplorer objIE = new SHDocVw.InternetExplorer(); //オブジェクトを作成 objIE.Navigate("about:blank"); //空ページの表示 objIE.Visible = true; //IEを表示 String encodedKeyword = System.Web.HttpUtility.UrlEncode(this.textBox1.Text, System.Text.Encoding.UTF8); String targetUrl = "https://search.yahoo.co.jp/search?b=0&p=" + encodedKeyword; objIE.Navigate(targetUrl); //読み込み完了まで待つ while (objIE.Busy || objIE.ReadyState != SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE) { //無処理 System.Windows.Forms.Application.DoEvents(); System.Threading.Thread.Sleep(100); } var ObjHtml = (mshtml.HTMLDocument)objIE.Document; var bodys = ObjHtml.getElementsByTagName("body"); foreach (mshtml.IHTMLElement element in bodys) { if (element != null) { Debug.WriteLine(element.outerHTML); } } System.Threading.Thread.Sleep(5000); if (objIE != null) { objIE.Quit(); } } } } |
ブラウザが固まらないようにする別スレッド化
あと、ブラウザ操作を繰り返すときに、GUIが固まってしまう現象を回避するため、別スレッドで操作するようにしても良いです。
これは少し中級者向けなので、最後に添えます。
そのためには、backgroundWorkerのコンポーネントを追加し、
- backgroundWorker1_ProgressChanged
- backgroundWorker1_RunWorkerCompleted
- backgroundWorker1_DoWork
というメソッドを作成したうえで、イベント発生時に呼ばれるように設定します。
副業でネットビジネスに取り組んでいるぱーくんと申します。
激務でも増えない給料に失望し、将来のために別の収入源が欲しい!の一心でネットビジネスをはじめ、2018年4月に20万円達成。
ひと月36万アクセスあるサイトを作ったノウハウは無料で公開中。 ⇒⇒コチラ
ネットビジネスで未来を夢見れる方を一人でも増やしたいと思っています。
誰でも最初は初心者。
【やってみたいけど、初心者だから不安】
という方は、ぜひお気軽にお問合せください♪