Поиск и автоматическое заполнение форм входа в HTML в UIWebView с использованием JavaScript

У меня есть UIWebView, который действует как интернет-браузер и загружает HTML-страницы веб-страниц, на которых он находится.

в webViewController, метод webViewDidFinishLoad, загрузил бы HTML с веб-страницы, когда веб-страница завершит загрузку в UIWebView.

Из HTML я бы хотел, чтобы сито выводило текстовые поля, чтобы облегчить автоматическую совокупность этого текстового поля со значениями, хранящимися в моей базе данных.

Любые методы для этого? Метод должен иметь возможность работать на всех веб-сайтах.

Установить текст для текстового поля в UIWebView почти что может мне помочь, но я пробовал его, и текстовое поле никогда не заполнялось.

На странице входа в систему будут два текстовых поля поэтому я попытался использовать

document.getElementsByTagName('INPUT')[0].value
document.getElementsByTagName('INPUT')[1].value 

для ввода значений, но без магии.

Изменить: Я пробовал другое положение в массиве. имя пользователя и пароль для Facebook - [3] и [4], тогда как для амазонки это [11] и [14]. поэтому положение того, где поля используют вышеупомянутый метод, является случайным. Любое другое предложение, которое будет работать для всего веб-сайта?

Edit2: я мог попробовать

document.getElementsById('id_name').value

но метод ID не будет работать для меня, поскольку мне нужен универсальный метод, который будет идентифицировать текстовые поля на любых веб-сайтах (все веб-сайты используют разные идентификационные имена)

Также мне кажется, что некоторые веб-сайты последовательно устанавливают этот tabindex = "1" для имени пользователя и tabindex = "2" для пароля.

например, на веб-странице, например Facebook:

<input type="text" class="inputtext" name="email" id="email" value="" tabindex="1" />
<input type="password" class="inputtext" name="pass" id="pass" tabindex="2" /> 

амазонка:

<input id="ap_email" name="email" value="" type="email" size="30" maxlength="128" tabindex="1" autocorrect="off" autocapitalize="off" />
<input id="ap_password" name="password" type="password" maxlength="1024" size="20"  tabindex="2" onkeypress="displayCapsWarning(event,'ap_caps_warning', this);" class="password"/> 

dbs bank:

<input type="text" tabindex="1" maxlength="20" size="32" name="UID" id="UID">
<input type="password" onkeyup="keyUp(event)" onkeydown="return onlyNumerics(event)" tabindex="2" maxlength="9" size="32" name="PIN" id="PIN" autocomplete="off">

но я не видел этот tabindex в google:

<input type="text" spellcheck="false" name="Email" id="Email" value="">
<input type="password" name="Passwd" id="Passwd">

любое предложение?

Конечная цель состоит в том, чтобы иметь возможность вычеркивать поле имени пользователя и пароля для всех/любых веб-сайтов. =)

Ответ 1

ОК, так что для этого нет единого размера. Вы можете получить довольно близко, но он никогда не будет работать на каждом веб-сайте, поскольку на веб-сайте может быть несколько форм входа или несколько полей, которые составляют имя пользователя (некоторые банки имеют это).

Но это поможет вам в правильном направлении. Чтобы получить все поля пароля (в основном только одно), используйте это:

document.querySelectorAll("input[type='password']")

Чтобы получить все поля ввода текста, используйте это:

document.querySelectorAll("input[type='text']")

Для полей ввода текста вы, скорее всего, получите несколько результатов (возможно, поля поиска и прочее). Таким образом, вам придется перебирать их и искать общие идентификаторы или имена, такие как "имя пользователя", "пользователь", "имя пользователя", "UID" и т.д.

Вот как вы могли бы использовать его в Objective-C:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    NSString *savedUsername = @"peter";
    NSString *savedPassword = @"Pan123";

    if (savedUsername.length != 0 && savedPassword.length != 0) { 
        //create js strings
        NSString *loadUsernameJS = [NSString stringWithFormat:@"var inputFields = document.querySelectorAll(\"input[type='text']\"); \
        for (var i = inputFields.length >>> 0; i--;) { inputFields[i].value = '%@';}", savedUsername];
        NSString *loadPasswordJS = [NSString stringWithFormat:@"document.querySelectorAll(\"input[type='password']\").value ='%@'", savedPassword];

        //autofill the form
        [self.webView stringByEvaluatingJavaScriptFromString: loadUsernameJS];
        [self.webView stringByEvaluatingJavaScriptFromString: loadPasswordJS];
    }
}

Обратите внимание: он заполняет каждое текстовое поле именем пользователя и только первым паролем с паролем.

Enjoy.

Ответ 2

Основываясь на предыдущем ответе, я создал эти 3 метода.

Этот метод заполнит поля имени пользователя/электронной почты, которые должны работать во многих случаях:

- (void)completeUserFieldsForWebView:(UIWebView *)webView withUsername:(NSString *)username {

    NSString *loadUsernameJS =
    [NSString stringWithFormat:@"var inputFields = document.querySelectorAll(\"input[type='email']\"); \
     for (var i = inputFields.length >>> 0; i--;) { inputFields[i].value = '%@';}", username];
    NSString *loadText =
    [NSString stringWithFormat:@"var inputFields = document.querySelectorAll(\"input[type='text']\"); \
     for (var i = inputFields.length >>> 0; i--;) { inputFields[i].value = '%@';}", username];
    [webView stringByEvaluatingJavaScriptFromString: loadUsernameJS];
    [webView stringByEvaluatingJavaScriptFromString: loadText];

}

В этом поле будут заполнены поля пароля:

- (void)completePasswordFieldsForWebView:(UIWebView *)webView withPassword:(NSString *)password {

    NSString *loadPasswordJS =
    [NSString stringWithFormat:@"var passFields = document.querySelectorAll(\"input[type='password']\"); \
     for (var i = passFields.length>>> 0; i--;) { passFields[i].value ='%@';}", password];
    [webView stringByEvaluatingJavaScriptFromString: loadPasswordJS];

}

И чтобы выполнить вход:

- (void)clickOnSubmitButtonForWebView:(UIWebView *)webView {

    NSString *performSubmitJS = @"var passFields = document.querySelectorAll(\"input[type='submit']\"); \
    passFields[0].click()";
    [webView stringByEvaluatingJavaScriptFromString:performSubmitJS];

} 

Ответ 3

Я не думаю, что найти ссылку на входные элементы будет сложно с помощью javascript, но это исправляет их, что не просто с UIWebView.

Хакерный способ добиться того, что вы хотите в том, как вы описываете, можно сделать, получив HTML из UIWebView, изменив его, а затем загрузив обратно. Например:

// Get the HTML from the UIWebView
NSMutableString *html = [[[self.webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.outerHTML;"] mutableCopy] autorelease];

// Find the range of the first input element.
NSRange firstInputRange = [html rangeOfString:@"<input" options:NSCaseInsensitiveSearch];
// Check if it was found...
if (firstInputRange.location != NSNotFound) {
    // Add replace with the populated value attribute appended.
    [html replaceCharactersInRange:firstInputRange withString:@"<input value='username'"];

    // Now do the same for the second input range, checking the html after the first input.
    NSRange secondInputRange = [html rangeOfString:@"<input" options:NSCaseInsensitiveSearch range:NSMakeRange(firstInputRange.location+firstInputRange.length, html.length - firstInputRange.location - firstInputRange.length)];
    // And if found, append the populated value attribute.
    if (secondInputRange.location != NSNotFound) {
        [html replaceCharactersInRange:secondInputRange withString:@"<input value='password'"];
    }

}

// Finally, load the amended HTML back into the UIWebView/
[self.webView loadHTMLString:html baseURL:nil];

Ответ 4

У меня возникли проблемы с поиском полей, поэтому я адаптировал код для более конкретных целей:

   - (void)webViewDidFinishLoad:(UIWebView*)theWebView
    {

    NSString *savedUsername = @"username";
    NSString *savedPassword = @"pass";

      if (savedUsername.length != 0 && savedPassword.length != 0) {

          NSString *loadUsernameJS = [NSString stringWithFormat:@"var inputFields = document.getElementsByTagName('input'); \
                                for (var i = inputFields.length >>> 0; i--;) { if(inputFields[i].name == 'username') inputFields[i].value = '%@';}", savedUsername];

          NSString *loadPasswordJS = [NSString stringWithFormat:@" \
                                for (var i = inputFields.length >>> 0; i--;) { if(inputFields[i].name == 'password') inputFields[i].value = '%@';}", savedPassword];

    //autofill the form
       [theWebView stringByEvaluatingJavaScriptFromString: loadUsernameJS];
       [theWebView stringByEvaluatingJavaScriptFromString: loadPasswordJS];
      }


    return [super webViewDidFinishLoad:theWebView];
  }