2013年6月10日月曜日

JScriptでIEを操作

JScriptでIEを自動操作するための関数のメモ。テスト等で使う。
素直にSelenium等のテストツールを使えばいいのだが、客先の環境でなかなかフリーソフトを導入できない場合に使う。
IEしか操作はできないけどね...。

①テキストフィールドに入力するための関数。
テキストタグの指定はid属性もしくはname属性。
//****************************************************************
//テキスト、パスワードを入力
//****************************************************************
function input_text( objIE, input_type, tag_id, input_name, input_value )
{
  var objDoc = objIE.document;
  if(! objDoc) return 1;
  if( tag_id ) return input_text_specified_id( objDoc );
  else if( input_name ) return input_text_specified_name( objDoc );
  else return 1;
  //id属性がである要素に対して入力
  function input_text_specified_id( objDoc ) {
    var objTxt = objDoc.getElementById( tag_id );
    if( ! objTxt ) return 1;
    var tag_name = objTxt.tagName;
    var type = objTxt.type;
    if( ! tag_name || ! type ) return 1;
    if( tag_name.toUpperCase() == "INPUT" && type == input_type ) return input(objTxt);
    return 1;
  }
  //name属性がである要素(1番目の要素)に対して入力
  function input_text_specified_name( objDoc ) {
    var objInputs = objDoc.getElementsByTagName("input");
    if(! objInputs) return 1;
    for(var i = 0; i < objInputs.length; i++) {
      var type = objInputs.item(i).type;
      var name = objInputs.item(i).name;
      if( ! type || ! name ) continue;
      if( type == input_type && name == input_name ) return input(objInputs.item(i));
    }
    return 1;
  }
  //入力
  function input(objTxt) {
    objTxt.focus();
    WScript.Sleep( interval );
    objTxt.value = input_value;
    return 0;
  }
}

②ボタン、ラジオボタン、チェックボックスを押下するための関数。
 タグの指定はid属性、name属性、もしくは任意の属性。
//****************************************************************
//ボタン、ラジオボタン、チェックボックスをクリック
//****************************************************************
function click_btn( objIE, input_type, tag_id, input_name, attr_name, attr_value )
{
  var objDoc = objIE.document;
  if(! objDoc) return 1;
  if( tag_id ) return click_btn_specified_id( objDoc );
  else if( input_name || (attr_name && attr_value) ) {
    return click_btn_specified_name_and_value( objDoc );
  }
  else return 1;
  
  //id属性が"tag_id"である要素を押下
  function click_btn_specified_id( objDoc ) {
    var objBtn = objDoc.getElementById(tag_id);
    if(! objBtn) return 1;
    var tag_name = objBtn.tagName;
    var type = objBtn.type;
    if(! tag_name || ! type) return 1;
    if( tag_name.toUpperCase() == "INPUT" && type == input_type ) return click(objBtn);
    return 1;
  }
  //name属性が"input_name"である要素(1番目の要素)、かつ
  //"attr_name"属性が"attr_value"である要素を押下
  function click_btn_specified_name_and_value( objDoc ) {
    var objInputs = objDoc.getElementsByTagName("input");
    if(! objInputs) return 1;
    for(var i = 0; i < objInputs.length; i++) {
      var type = objInputs.item(i).type;
      if(! type) continue;
      if(type != input_type) continue;
      if( input_name ) {
        var name = objInputs.item(i).name;
        if( ! name ) continue;
        if( name != input_name ) continue;
      }
      if(attr_name && attr_value) {
        var atr = objInputs.item(i).attributes.getNamedItem(attr_name);
        if( ! atr ) continue;
        if( ! atr.value ) continue;
        if( atr.value != attr_value ) continue;
      }
      return click(objInputs.item(i));
    }
    return 1;
  }
  //クリック
  function click(objBtn) {
    objBtn.focus();
    WScript.Sleep( interval );
    objBtn.click();
    return 0;
  }
}

③リンクをクリックするための関数。
タグの指定はid属性、href属性、内部テキスト、もしくは、内部画像タグのalt属性。
//****************************************************************
//リンクをクリック
//****************************************************************
function click_link( objIE, tag_id, a_href, innerText, img_alt )
{
  var objDoc = objIE.document;
  if(! objDoc) return 1;
  if(tag_id) return click_link_specified_id( objDoc );
  else if( a_href ) return click_link_specified_href( objDoc );
  else if( innerText ) return click_link_specified_innerText( objDoc );
  else if( img_alt ) return click_link_specified_img_alt( objDoc );
  else return 1;
  
  //id属性が"tag_id"である要素をクリック
  function click_link_specified_id( objDoc ) {
    var objLink = objDoc.getElementById(tag_id);
    if( ! objLink ) return 1;
    var tag_name = objLink.tagName;
    if( ! tag_name ) return 1;
    if( tag_name.toUpperCase() == "A" ) return click(objLink);
    return 1;
  }
  //href属性が"a_href"である要素をクリック
  function click_link_specified_href( objDoc ) {
    var objLinks = objDoc.getElementsByTagName("a");
    if(! objLinks) return 1;
    for(var i = 0; i < objLinks.length; i++) {
      var href = objLinks.item(i).href;
      if(! href) continue;
      if(href == a_href) return click(objLinks.item(i));
    }
    return 1;
  }
  //内部テキストが"innerText"である要素をクリック
  function click_link_specified_innerText( objDoc ) {
    var objLinks = objDoc.getElementsByTagName("a");
    if(! objLinks) return 1;
    for(var i = 0; i < objLinks.length; i++) {
      var intxt = objLinks.item(i).innerText;
      if(intxt == innerText) return click(objLinks.item(i));
    }
    return 1;
  }
  //内部画像のalt属性が"img_alt"である要素をクリック
  function click_link_specified_img_alt( objDoc ) {
    var objLinks = objDoc.getElementsByTagName("a");
    if(! objLinks) return 1;
    for(var i = 0; i < objLinks.length; i++) {
      var imgs = objLinks.item(i).getElementsByTagName("img");
      if(! imgs) continue;
      var alt = imgs.item(0).attributes.getNamedItem("alt");
      if(! alt) continue;
      if(alt.value == img_alt) return click(objLinks.item(i));
    }
    return 1;
  }
  //クリック
  function click(objLink) {
    objLink.focus();
    WScript.Sleep( interval );
    objLink.click();
    return 0;
  }
}

④セレクトボックスを選択するための関数。
タグの指定はid属性もしくはname属性。
//****************************************************************
//セレクトボックスを選択
//****************************************************************
function select_option( objIE, tag_id, input_name, select_number )
{
  var objDoc = objIE.document;
  if(! objDoc) return 1;
  if( tag_id ) return select_option_specified_id( objDoc );
  else if( input_name  ) return select_option_specified_name( objDoc );
  else return 1;
  
  //id属性が"tag_id"である要素を選択
  function select_option_specified_id( objDoc ) {
    var objSlct = objDoc.getElementById(tag_id);
    if( ! objSlct ) return 1;
    var tag_name = objSlct.tagName;
    if( ! tag_name ) return 1;
    if( tag_name.toUpperCase() == "SELECT" ) return select(objSlct);
    return 1;
  }
  //name属性が"input_name"である要素を選択
  function select_option_specified_name( objDoc ) {
    var objSlcts = objDoc.getElementsByTagName("select");
    if( ! objSlcts ) return 1;
    for(var i = 0; i < objSlcts.length; i++) {
      var name = objSlcts.item(i).name;
      if( ! name ) continue;
      if( name == input_name ) return select(objSlcts.item(i));
    }
    return 1;
  }
  //クリック
  function select(objSlct) {
    objSlct.focus();
    WScript.Sleep( interval );
    objSlct.selectedIndex = select_number;
    return 0;
  }
}

⑤クリック後に新規画面が開く場合、その画面のオブジェクトを返す。
どの画面かは タイトルで指定する。
function focusWindow( title ) {
  var MAX_COUNT = 10;
  var objShell = new ActiveXObject("Shell.Application");
  var objWins = objShell.Windows();
  if( ! objWins ) return null;
  
  for(var t = 0; t < MAX_COUNT; t++) {
    for(var i = 0; i < objWins.Count; i++) {
      var item = objWins.item(i);
      try {
        var ifn = item.FullName;
        if( ! ifn ) continue;
        if(item.FullName.match(/iexplore.exe$/i)) {
          var objDoc = item.document;
          if( ! objDoc ) continue;
          if( ! objDoc.title ) continue;
          if( objDoc.title == title ) {
            return item;
          }
        }
      }
      catch (e) {}
    }
  }
  return null;
}



使い方は以下のようになる。
以下は乗り換え案内のページの操作例。
var interval = 100;//操作の間(100ms)
var ie = WScript.CreateObject("InternetExplorer.Application");
//乗り換え案内のページを開く
ie.Navigate( "http://www.ekikara.jp/top.htm" );
ie.Visible = true;
//ビジー状態を待つ(参考:http://d.hatena.ne.jp/language_and_engineering/20090713/p1)
waitIE( ie );

//乗り換え案内のオプションリンクをクリック
click_link( ie, null, "http://www.ekikara.jp/cgi-bin/route.cgi", null, null);
waitIE( ie );
//乗車駅入力
input_text( ie, "text", null, "intext", "東京");
//降車駅入力
input_text( ie, "text", null, "outtext", "博多");
//飛行機のチェックをクリックして外す
click_btn( ie, "checkbox", null, "airplane", null, null );
//新幹線のチェックをクリックして外す
click_btn( ie, "checkbox", null, "sprexprs", null, null );
//表示順序で乗車距離をクリックする
click_btn( ie, "radio", null, "sort", "value", "meter" );
//検索ボタンを押下
click_btn( ie, "image", null, null, "alt", "検索" );
waitIE( ie );
//修正画面でもう一度検索ボタンを押下
click_btn( ie, "image", null, null, "alt", "検索" );
waitIE( ie );

あとは、これらの関数を使えば自動操作といきたいところだが、まだできないものもある。
例えば、javascriptのalert等で表示されるダイアログの操作とか。以下のページに詳しく書かれている。
http://d.hatena.ne.jp/language_and_engineering/20100727/p1