I am trying to automate a website login for:
https://www.check-mot.service.gov.uk/
However the ID of the input textbox changes randomly, is there a way to scan through the code and establish it's current ID?
I have tried using GetElementsByTagName but that did not work.
When I use the inspect element it takes me to this line:
It is the 202413237510 that changes randomly of the line of code below.
<input name="202413237510" class="form-control" id="202413237510" type="text" value="">
The surrounding code below:
<form name="moth-search" id="EVL" action="/" method="POST">
<fieldset>
<legend class="form-title heading-medium visuallyhidden">Enter the vehicle registration</legend>
<input name="_csrf_token" type="hidden" value="7A9313B6-6834-04E2-56BE-D6966FFE041F">
<div class="form-group apiary-22453 ddt">
<label class="form-label form-label-bold" for="1700806253">
<span>Do not fill this field</span>
<span class="form-hint">For example, CU57ABC</span>
</label>
<input name="1700806253" tabindex="-1" class="form-control" id="1700806253" type="text" value="">
</div>
<div class="form-group is-on-show tyu-33">
<label class="form-label form-label-bold" for="reg-number">
<span>Do not enter anything in this field</span>
<span class="form-hint">For example, CU57ABC</span>
</label>
<input name="reg-number" tabindex="-1" class="form-control" id="reg-number" type="text" value="">
</div>
<div class="form-group hoth-field it-290">
<label class="form-label form-label-bold" for="202413237510">
<span><span class="sr-only">Enter your</span> Registration number (number plate) <span class="sr-only">into this field only</span></span>
<span class="form-hint">For example, CU57ABC</span>
</label>
<input name="202413237510" class="form-control" id="202413237510" type="text" value="">
</div>
<div class="form-group it-290 salad-box">
<label class="form-label form-label-bold" for="vehicle-manufacturer">
<span>This field should be left empty</span>
<span class="form-hint">For example, CU57ABC</span>
</label>
<input name="vehicle-manufacturer" tabindex="-1" class="form-control" id="vehicle-manufacturer" type="text" value="">
</div>
<div class="form-group keep-hidden isOnshow">
<label class="form-label form-label-bold" for="registration">
<span>Do not fill this field</span>
<span class="form-hint">For example, CU57ABC</span>
</label>
<input name="registration" tabindex="-1" class="form-control" id="registration" type="text" value="">
</div>
<div class="form-group bee-hive tyu-33">
<label class="form-label form-label-bold" for="registration-number">
<span>Do not fill this field</span>
<span class="form-hint">For example, CU57ABC</span>
</label>
<input name="registration-number" tabindex="-1" class="form-control" id="registration-number" type="text" value="">
</div>
You don't show any code so I'm not sure how you're getting at the document. My example uses the IE object from MS Internet Controls and then RegExp object from VBScript Regular Expressions.
You should be able to just pull out the RegExp constant, variables and code to get your id from your document body variable.
This regular expression searches for matching input elements that consist of numbers in the their name - but the trick is it ignores the ones that have tabindex="-1" in the definition.
Sub ExtractID()
'To use this example you'll need two references
'Open the VBA editor and pull down Tools | References menu
'- select "Microsoft Internet Controls"
'- select "Microsoft VBScript Regular Expressions 5.5"
Const FIND_NEW_ID As String = "name=""(\d)*"" class=""form-control"" id=""(\d)*"""
Dim ie As SHDocVw.InternetExplorer
Dim regEx As New RegExp
Dim idMatches As MatchCollection
Dim idMatch As Match
Dim strHTML As String
Dim strID As String
Set ie = New SHDocVw.InternetExplorer
With ie
.Navigate "https://www.check-mot.service.gov.uk/"
Do While .ReadyState <> READYSTATE_COMPLETE Or .Busy = True
DoEvents
Loop
strHTML = ie.Document.body.innerHTML
'Set doc = .Document
'strHTML = doc.body.innerHTML
With regEx
.Global = True
.Multiline = True
.IgnoreCase = False
.Pattern = FIND_NEW_ID
End With
If regEx.Test(strHTML) Then
Set idMatches = regEx.Execute(strHTML)
If idMatches.Count = 1 Then
strID = Mid$(idMatches(0).Value, 7) ' remove name from front
strID = Left$(strID, InStr(strID, """") - 1) ' pull ID from double quotes
MsgBox "Found ID: " & strID
Else
MsgBox "Not Going to Work - we found multiples"
End If
Else
MsgBox ("No ID Found")
End If
End With
End Sub
Regex101.com is a great site for testing regular expressions against your HTML docs
Related
My view:
<div class="col-md-3">
<div class="form-group">
<label>Employee Id</label>
<input type="text" class="form-control" placeholder="Enter employee id" name="empid">
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label>Employee Name</label>
<input type="text" class="form-control" placeholder="Enter employee name" name="empname">
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label>Order Number</label>
<input type="number" class="form-control" placeholder="Enter order number" name="ordernumber" value="<?php echo $order_number;?>">
</div></div>
<div class="col-md-3">
<div class="form-group">
<label></label>
<a onclick="myFunctionfirst()" class="form-control">Proceed to order Create</a>
</div></div>
Once you click on 'proceed to order create' the second row is created. I want this to happen only when the first 3 fields in first row are filled. Please suggest on this
And this is my controller:
public function index()
{
$empid = $_POST['empid'];
If ($empid == ""){
$this->load->model('invoice_model');
$data['stat']= $this->invoice_model->get_stationary();
$data['order_numbers']= $this->invoice_model->get_countnumber();
$data['order_number']= $data['order_numbers'][0]->count+1;
$data['page']='invoice/invoice_view';
$this->load->view("template",$data);
}
}
And it's throwing an error undefined index empid
Welcome to stackoverflow. what you can do is save the input as a variable Store input from a text field in a PHP variable
this method is however a bit unsafe. to secure the input you can use https://www.w3schools.com/php/func_string_htmlspecialchars.asp
https://www.php.net/manual/en/function.htmlspecialchars.php
and once you have the variables just simply check if the variable is empty or not
public function index()
{
$firstname = $_POST['firstname'];
If ($firstname != ""){
$this->load->model('invoice_model');
$data['stat']= $this->invoice_model->get_stationary();
$data['order_numbers']= $this->invoice_model->get_countnumber();
$data['order_number']= $data['order_numbers'][0]->count+1;
$data['page']='invoice/invoice_view';
$this->load->view("template",$data);
}
}
$_POST is how the data is being send. here they explain the difference between POST and GET https://www.quora.com/What-is-the-difference-between-PHPs-get-method-post-method
'firstname' is the name of the input. in your case its <input type="text" class="form-control" placeholder="Enter employee id" name="empid"> so it should be $_POST['empid']
the data is being send with the submit button. instead of using the <a> tag you should use the <button type="submit"> tag also, wrap the inputs in a form tag.
Here is my vba code.
It works up until the point where I also keep getting messages that say object has disconnected from its client. I don't want to use sendkeys or Selenium as my colleagues will not be able to duplicate and run this form then. I wish to make it robust.
Sub exceltoweb()
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
IE.navigate "https://fans-dub.amazon.com/"
IE.Visible = True
While IE.Busy
Do
DoEvents
Loop Until IE.readyState = READYSTATE_COMPLETE
Wend
delay 5
IE.document.all("submitterId").Value = ("fahac")
delay 2
IE.document.all("to").Value = ("ceezeala")
delay 3
IE.document.all("messageText").Value = ("10 errors")
delay 3
IE.document.all("/images/send-button.gif").Click
Application.StatusBar = "Form Submitted"
Set IE = Nothing
Application.ScreenUpdating = True
End Sub
This is the HTML:
id="simpleSendMessageForm" method="post">
<div id="outerDiv">
<label>From:</label>
<div class="formElement">
<input name="submitterId" type="text" size="16" value="fahac" readonly />
</div>
<div class="break"></div>
<label>
<abbr title="A comma separated list of user ids who will receive this message">To:</abbr>
</label>
<div class="formElement">
<input name="to" type="text" size="16" value="" />
</div>
<div class="break"></div>
<label>
<abbr title="A comma separated list of manager's user ids. The message will be sent to all people who report directly to one of these managers">Direct reports of:</abbr>
</label>
<div class="formElement">
<input name="directReports" type="text" size="16" />
</div>
<div class="break"></div>
<textarea rows="5" name="messageText"></textarea>
</div>
<div class="break"></div>
<span class="right">
<span id="ssmf-loading" class="ajaxloading"><img src="/images/ajax-loading.gif" alt="Loading..." /></span>
<input type="image" src="/images/send-button.gif" />
</span>
</form>
</div>
</fieldset>
</div>
<!-- SEARCH -->
<!-- Search tab is excluded from EU pages for compliance with European data protection law -->
<div class="clear"></div>
<!-- MESSAGE LIST -->
<div class="qsection">
<fieldset class="roundborder snx2">
<legend id="messageListTitle" class="qsectionTitle">My Messages (Last 3 days)</legend>
<div id="myMessages" class="qsectionBody">
The boxes I want to enter a text into does not have an ID, just names. I wish to populate 3 boxes and hit send for which the send does not have ID either.
I think these links may help you:
http://automatetheweb.net/
http://automatetheweb.net/common-vba-methods-properties-web-automation/
I'm sure that you can find those elements using something like
"IE.document.getElementByName" or
"IE.document.getElementsByClassName"
change those values using .value
and click using click() method
I am trying to get a simple form to post to my sql database, but nothing is happening when i click on it. I have tried runat="Server, onclick, onserverclick tags but nothing is happening.
I am new to html forms so dont know if i should have the button outside of the actual form to do this? any help is greatly appreciated
Below is the html code
<div class="register-content" ">
<form method="POST" class="margin-bottom-0">
<label class="control-label">Name <span class="text-danger">*</span></label>
<div class="row row-space-10">
<div class="col-md-6 m-b-15">
<input id="First_Text" type="text" class="form-control" placeholder="First name" required />
</div>
<div class="col-md-6 m-b-15" >
<input id="Last_Text" type="text" class="form-control" placeholder="Last name" required />
</div>
</div>
<label class="control-label">Email <span class="text-danger">*</span></label>
<div class="row m-b-15">
<div class="col-md-12">
<input id="Email_Text" type="text" class="form-control" placeholder="Email address" required />
</div>
</div>
<label class="control-label">Password <span class="text-danger">*</span></label>
<div class="row m-b-15">
<div class="col-md-12">
<input id="Pass_Text" type="password" class="form-control" placeholder="Password" required />
</div>
</div>
<div class="register-buttons">
<button runat="server" onserverclick="ValidateUser" type="button" class="btn btn-primary btn-block btn-lg">Sign Up</button>
</div>
<div class="m-t-20 m-b-40 p-b-40">
Already a registered user? Click here to login.
</div>
<hr />
<p class="text-center">
© NZAB All Right Reserved 2019
</p>
</form>
</div>
And here is the code behind
Protected Sub ValidateUser(sender As Object, e As EventArgs)
Dim connect As New SqlConnection(ConfigurationManager.ConnectionStrings("NZABFMAD_Users").ToString())
Using coa As New SqlCommand()
With coa
.Connection = connect
.CommandType = CommandType.Text
End With
Try
connect.Open()
Dim insertcmd As String
insertcmd = "INSERT INTO [New_User] (Username,[First name],[Last name],Email,Password) values (#User_Text,#First_Text,#Last_Text,#Email_Text,#Pass_Text)"
coa.CommandText = insertcmd
coa.Parameters.AddWithValue("#User_Text", Request.Form("User_Text"))
coa.Parameters.AddWithValue("#First_Text", Request.Form("First_Text"))
coa.Parameters.AddWithValue("#Last_Text", Request.Form("Last_Text"))
coa.Parameters.AddWithValue("#Email_Text", Request.Form("Email_Text"))
coa.Parameters.AddWithValue("#Pass_Text", Request.Form("Pass_Text"))
coa.ExecuteNonQuery()
connect.Close()
MsgBox("success insert")
Catch ex As Exception
MsgBox("Fail to Save to database")
End Try
End Using
End Sub
Granted i will be salting/hashing passwords when storing in sql, but for now i just want the button to actually fire the event!
First of all you need to give each input field a name, as that is what identifies them when posted to the server. The id is merely for client-side identification (e.g. via JavaScript).
<input id="First_Text" name="First_Text" type="text" class="form-control" placeholder="First name" required />
Secondly, the button merely calls the callback on the server. It doesn't actually submit the form, so in this case Request.Form will be empty.
For standard HTML forms you need to use an <input type="submit"/> so that your form is actually submitted and its data sent to the server. You can then invoke the reading of its data from the Page_Load handler.
<div class="register-buttons">
<input type="submit" class="btn btn-primary btn-block btn-lg" value="Sign up"/>
</div>
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'Check if this is a POST request.
If HttpContext.Current.Request.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase) Then
DoSignUp()
End If
End Sub
Private Sub DoSignUp()
'Put your code from ValidateUser here.
End Sub
Although you could, like Andrew Morton said in the comments, replace the form and your input fields with ASP.NET controls and handle it via postback instead. I'm not sure which method is preferred in this case as I haven't worked much with WebForms. Personally, I'd use a form like you do now.
First time poster, long time user.
I'm trying to write a script in VBA to login to a site to then extract data at a later step.
I've hit a road block with trying to logon to the site, there is three classes that change once you manually fill in the username and password and two aria-invalid that turn from true to false. Unfortunately, this doesn't update if you try and fill in the forms via VBA.
This is the VBA code I currently have
Option Explicit
Sub LoginToSite()
Dim IE As New SHDocVw.InternetExplorer
IE.Visible = True
IE.navigate "https://website.com.au"
Do While IE.ReadyState <> READYSTATE_COMPLETE
Loop
IE.Document.forms("form").elements("username").Value = "FredFlinstone"
IE.Document.forms("form").elements("password").Value = "Password000"
IE.Document.forms("form").elements("submit-button").Click
End Sub
This is the HTML before manual text is added into the forms:
`<form name="form" class="login-form ng-pristine ng-invalid ng-invalid-required" novalidate="" autocomplete="off">
<div class="field-container">
<label for="username">
Username
</label>
<input name="username" class="ng-pristine ng-empty ng-invalid ng-invalid-required ng-touched" id="username" aria-invalid="true" required="" type="text" ng-keydown="vm.loginOnKeyEnter($event)" ng-class="vm.usernameEmptyClass" ng-model="vm.username">
</div>
<div class="field-container ">
<label for="password">
Password
</label>
<input name="password" class="ng-pristine ng-untouched ng-empty ng-invalid ng-invalid-required" id="password" aria-invalid="true" required="" type="password" ng-keydown="vm.loginOnKeyEnter($event)" ng-class="vm.passwordEmptyClass" ng-model="vm.password">`
These are the parts that change in the HTML if you manually add text.
Form div
<form name="form"
class="login-form ng-dirty ng-valid-parse ng-valid ng-valid-required"
novalidate=""
autocomplete="off">
Username Div
<input name="username"
class="ng-touched ng-not-empty ng-dirty ng-valid-parse ng-valid ng-valid-required"
id="username"
aria-invalid="false"
required=""
type="text"
ng-keydown="vm.loginOnKeyEnter($event)"
ng-class="vm.usernameEmptyClass"
ng-model="vm.username">
Password Div
<input name="password"
class="ng-not-empty ng-dirty ng-valid-parse ng-valid ng-valid-required ng-touched"
id="password"
aria-invalid="false"
required=""
type="password"
ng-keydown="vm.loginOnKeyEnter($event)"
ng-class="vm.passwordEmptyClass"
ng-model="vm.password">
Very keen to learn what I need to change in order to trigger the site into realising there is text within the boxes to be able to login.
I've still got my L plates on with VBA, so code will most definitely not be the most efficient code, but keen to hear of better methods to executing the above
Thanks in advance Mr Swan
Try to use the .Focus method to focus the TextBox first, then use the SendKeys statement to enter the value.
The below code should work if it's single page but you'll have to fill out the SignIn Div information portion since this doesn't appear to be a valid URL. Just follow the same format and note that everything is case sensitive. TKs.
Sub LoginToSite()
Const cURL = "https://website.com.au"
Const cusername = "FredFlinstone"
Const cpassword = "Password000"
Dim IE As InternetExplorer
Dim doc As HTMLDocument
Dim LoginForm As HTMLFormElement
Dim UsernameInputBox As HTMLInputElement
Dim PasswordInputBox As HTMLInputElement
Dim SigninButton As HTMLInputButtonElement
Set IE = New InternetExplorer
IE.Visible = True
IE.navigate cURL
'Wait for initial page to load
Do While IE.readyState <> READYSTATE_COMPLETE Or IE.Busy: DoEvents: Loop
Set doc = IE.document
'Get the only form on the page
Set LoginForm = doc.forms(0)
'Get the Username textbox and populate it
'input name="username" id="username" size="18" value="" class="ng-touched ng-not-empty ng-dirty ng-valid-parse ng-valid ng-valid-required" type="text"
Set UsernameInputBox = doc.getElementById("username")
UsernameInputBox.Value = cusername
'Get the Password textbox and populate it
'input name="password" id="password" size="18" class="ng-not-empty ng-dirty ng-valid-parse ng-valid ng-valid-required ng-touched" type="text"
Set PasswordInputBox = doc.getElementById("password")
PasswordInputBox.Value = cpassword
'Get the form input button and click it
'button class="XXXXX" name="XXXXX" id="XXXXX" value="XXXXX" type="text"
Set SigninButton = doc.getElementById("XXXXX")
SigninButton.Click
'Wait for the new page to load
Do While IE.readyState <> READYSTATE_COMPLETE Or IE.Busy: DoEvents: Loop
End Sub
Is everything on one page or is it split between two pages like the Gmail login?
1 page example: enter username, enter password, click login
2 page example: enter username (click next), enter password, click login
I am trying to get a balance checker for Adnooka, but I can't even get past the login.
Here's the HTML:
</div>
<div class="control-group row-fluid">
<label class="row-fluid " for="inputPassword">Password <div class="pull-right"><a class="muted"><small><a href='http://adnooka.com/recover'>Forgot your password ?</a></small></a></div></label>
<div class="controls row-fluid input-append">
<input type="password" id="inputPassword" placeholder="Password" name="password" class="row-fluid" value=""> <span class="add-on"><i class="icon-lock"></i></span>
</div>
</div>
<div class="control-group row-fluid fluid">
<div class="controls span6">
</div>
<div class="controls span5 offset1" style=''>
<button type='submit' class="btn btn-default" style='float:right'>Login<i class="gicon-chevron-right"></i></a>
</div>
</div>
But the Button has no ID or Name, how can I click it?
How how can I return the value of a balance?
Here's what I've got so far:
WebBrowser1.Document.GetElementById("email").SetAttribute("value", textbox1.Text)
WebBrowser1.Document.GetElementById("password").SetAttribute("value", pass.Text)
Dim allelements As HtmlElementCollection = WebBrowser1.Document.All
For Each webpageelement As HtmlElement In allelements
If webpageelement.GetAttribute("type") = "submit" Then
webpageelement.InvokeMember("click")
End If
Next
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
WebBrowser1.Navigate("http://adnooka.com/login")
End Sub
You can invoke a submit on the form itself, you don't have to find a button to click.
This should work, if you have only one form on the page. If not, adjust the [0] to whatever is needed:
WebBrowser1.Document.Forms[0].InvokeMember("submit")
See http://msdn.microsoft.com/en-us/library/system.windows.forms.htmldocument.forms.aspx for more details.