Webページ ロボット化による操作

Webページのロボット化のサンプル
ある登録サイトに自動的に登録するもの。
登録データはEXCELから取得。事前にデータは用意しておく。
(ボタン等を押すだけのWebページの場合は不要)

ロボット対策してあるページは不可。

-  Thread.Sleep()はメソッドにasync付けて await Task.Delay()に置き換えた方が良いと思われる。
-  pickupPixelColor()はwebページが変わったか検知する為のもの。
例えば現在のページがXY 100,100がRGB10,10,10の場合、次の画面ではRGB50,50,50に変わるのであればその座標のRGB値を調べる事よりページが変わったか分かる。
-  ボタンを押すにはSetCursorPos()により該当ボタンにマウスを移動するかTABキーの送信によりフォーカスを移動させてLeft2()によりボタン投下する。
-  止めたい場合は、CTRL + ALT  + DEL　で暫く待ち、ESC により戻ると例外で止まる。
- 対象のコントロールの位置は画面最大化した状態で調べておく。
- 起動直後に該当WEBページ(edgeなど) を位置がズレるため最大化しておく。
- コンボボックスの場合、[0]～[10]の選択ができるコンボボックスでWebページを開いたときに[5]が出たり[6]が出るなど不定の場合、[8]を選択するにはそのコンボボックスにフォーカスを当ててカーソル上を10回送り、[0]に戻した後に8回カーソル下を送ることにより、[8]が設定できる。
- テキストボックスにフォーカス当てて、
Clipboard.SetText(id);　//貼り付けるデータコピー
SendKeys.Send("^v");     //ペースト
::: note info
あるサイトを自動化させるもので、そのページ用に作られているためご自身用に改変します。
安定動作させるまで微調整が必要になります。
3000回以上更新する必要に駆られて作りました。
手作業で数百時間掛かる作業が十数時間で終わりました。
しかもたまに誤動作していないか確認する程度。
:::
```c#
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using ClosedXML.Excel;
using System.Drawing;
using DocumentFormat.OpenXml.Drawing;

namespace AutoChg {

    public partial class Form1 : Form {

        private int R, G, B;
        ///////////////////////////////////////////////////////////////////
   
        public string K1;   //開始年
        public int    K2;   //開始月
        public int    K3;   //開始日

        static string NAME;

        //////////////////////////////////////////////////////////////////
        ///
        public Form1() {
            InitializeComponent();
            
            // 開始日を入力する欄があるので今日の日付取得
            DateTime dt = DateTime.Now;
            K1=dt.Year.ToString();
            K2=dt.Month;
            K3=dt.Day;
            

        }

        /////////////////////////////////////////////////////////////////////////////////////////////////
        // マウス制御用 移動とクリック
        [DllImport("user32.dll")]
        public static extern bool SetCursorPos(int X, int Y);

        [DllImport("USER32.dll", CallingConvention = CallingConvention.StdCall)]
        static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);

        private const int MOUSEEVENTF_LEFTDOWN = 0x2;   
        private const int MOUSEEVENTF_LEFTUP = 0x4;
        private const int MOUSEEVENTF_RIGHTDOWN = 0x8;
        private const int MOUSEEVENTF_RIGHTUP = 0x10;
        /////////////////////////////////////////////////////////////////////////////////////////////////
        

        private void Form1_Load(object sender, EventArgs e) {
            
            MessageBox.Show ("申請書作成　漢字OFF アクション展開しておく.");
            // 2秒以内に該当ページを最大化させること
            Thread.Sleep (2000);

            // webページに投入するデータをEXCELのセルから取得
            const string ExcelFilePath = @"C:\DB\AUTO.XLSX";
            var workbook = new XLWorkbook(ExcelFilePath);
            var worksheet = workbook.Worksheet("シムサ更新");
             
            // webトップへスクロール /////////////////////////////////
            SetCursorPos(3, 500);
            mouse_event (MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 
            mouse_event (MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 
            for (int x = 0; x < 30; x++) SendKeys.Send("{UP}");
            //////////////////////////////////////////////////////
            
            String ID;      // 対象GID
            String ENID;    // 

            for (int x = 2; x < 9999; x++) {
                // EXCELからデータ取得　id,名前,有効フラグ
                ID=  (worksheet.Cell(x, 2).GetString());
                NAME=(worksheet.Cell(x, 3).GetString());
                ENID=(worksheet.Cell(x, 4).GetString());

                if (ID == null || ID =="") break;
                if (ENID == "0" ) continue; // SKIP
               
                Auto(ID);
                Thread.Sleep (4500);
            }

            ///////////////////////////////////////////////////////

            MessageBox.Show ("END");
            this.Close();

        }

        public void Auto(string id) {
              
            Thread.Sleep (2000);

            // システム利用者変更申請書　左リンク  アクション展開して置く

            // マウスをxy 135,560に移動
            SetCursorPos(135, 560);
            
            // 左クリック
            Left2();
            Thread.Sleep (2500);

            // システム利用者変更申請書リンク
            SetCursorPos(812, 653);
            Thread.Sleep(10);
            Left2();
            Thread.Sleep(400);

            // 次ページがでるまで待機
            // XY 454,635が RGB51 51 51の色になったら待機から抜ける
            while (true){
                SetCursorPos     (454,635);
                pickupPixelColor (454,635);
                if ( R == 51 && G == 51 && B == 51) break;
            }

            Thread.Sleep(400);

            // 対象者選択ボタン
            SetCursorPos(1614, 642);
            Thread.Sleep(250);
            Left2();

            Thread.Sleep(1500);

            // ID欄
            SetCursorPos(944, 590);
            Thread.Sleep(20);
            Left2();

            Thread.Sleep(20);

            // ID クリップボード ctrl + v [ID]
            Clipboard.SetText(id);
            SendKeys.Send("^v");
            Thread.Sleep(100);

            SetCursorPos(1579, 588);
            Thread.Sleep (100);

            // 検索ボタン
            Left2();
            Thread.Sleep(1800);

            // 0件
            while (true){
                SetCursorPos     (491,652);
                pickupPixelColor (491,652);
                if ( R == 255 && G == 255 && B == 255) return; // 有効期限切れユーザは0件と表示されるのでリターン(期限切れ)
                else break;
            }

            // 〇選択
            SetCursorPos(438, 765);
            Left2();
            Thread.Sleep (250);

            // OK ボタン
            SetCursorPos(442, 899);
            Left2();
                                        
            while (true){
                SetCursorPos     (1800,700);
                pickupPixelColor (1800,700);
                if ( R == 5 && G == 121 && B == 177) break;
            }
            Thread.Sleep (2000);

            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // ここからシステム利用者変更申請書 
            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            
            // 氏名の下の名前欄まで移動
            for (int n = 0; n < 11; n++) SendKeys.Send("{TAB}");

            // 仕方ないので  下の名前の最後に  ﾃｽﾄ をつける
            Clipboard.SetText(NAME+"ﾃｽﾄ"); ////////////////////////////////////////////////// 
            SendKeys.Send ("^v");
            
            // 使用開始日へ移動
            for (int n = 0; n < 19; n++) SendKeys.Send("{TAB}");

            Clipboard.Clear();
            Clipboard.SetText(K1); ////////////////////////////////////////////////// 年
            SendKeys.Send ("^v");
          
            SendKeys.Send("{TAB}");
            for (int n = 0; n < 13; n++) {
                 SendKeys.Send("{UP}");
            }

            for (int n = 0; n < K2; n++) { ////////////////////////////////////////// 月
                 SendKeys.Send("{DOWN}");
            }
           
            SendKeys.Send("{TAB}");
            for (int n = 0; n < 32; n++) {
                 SendKeys.Send("{UP}");
            }

            for (int n = 0; n < K3; n++) { ////////////////////////////////////////// 日
                 SendKeys.Send("{DOWN}");
            }


            // 申請ボタンへ移動
            for (int n = 0; n < 4; n++) SendKeys.Send("{TAB}");

            Thread.Sleep(2200);

            // 申請ボタン
            SendKeys.Send("{ENTER}");

            // 次画面の申請ボタン
            SetCursorPos(600, 1139);
            Left2();

            Thread.Sleep (500);
            
           // return;
            
            
            // 以下の内容で申請書を申請しますか？ 申請ボタン
            while (true){
                SetCursorPos     (479,575);
                pickupPixelColor (479,575);
                if ( R == 132 && G == 191 && B == 249) break;
            }

            Thread.Sleep (10);
            SetCursorPos(479, 575);

            Left2();
        }
        
        public void Left2() {
            mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 
            Thread.Sleep (35);
            mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
        } 

        // 色取得
        private void pickupPixelColor(int x, int y){

            //    1x1のサイズのBitmapを生成する
            Bitmap bitmap = new Bitmap(1, 1);
            Thread.Sleep (100);

            //    先ほどのBitmapを元にGraphicsを生成する
            Graphics graphics = Graphics.FromImage(bitmap);
            Thread.Sleep (100);

            //    Bitmapに指定座標のスクリーンショットをコピーする
            graphics.CopyFromScreen(new System.Drawing.Point(x, y), new System.Drawing.Point(0, 0), new Size(1, 1));
            Color color = bitmap.GetPixel(0, 0);
            Thread.Sleep (100);

            R = color.R;
            G = color.G;
            B = color.B;
        }

    }
}
```