I am having a problem, what i am trying to do is:
I open a webpage with WWW::Mechanize, fill the username and password and log in.
The issue I am having is, after logging in I have to select the value from a dropdown list
and after that I have to press submit.
How can i do that?
The code which i have used is:
#!/usr/bin/perl
use LWP::UserAgent;
use WWW::Mechanize;
use HTTP::Cookies;
use strict;
my $username="123456";
my $password="XXXXX";
my $project="Systems";
my $agent = WWW::Mechanize->new();
$agent->get('http://www.XXXXX.com');
$agent->form_name("login_form");
$agent->field("txtLoginId", $username);
$agent->field("txtPassword", $password);
$agent->submit();
#Till now it has success full logined, From here it has to select one value from a drop #down box
$agent->form_name("frmProject");
$agent->field("cboProject", $project);
my $response=$agent->submit();
if ($response->is_success){
print "\nContent:\n";
print $response->as_string;
}elsif ($response->is_error){
print $response->error_as_HTML;
}
WWW::Mechanize has a click method that you can use to click on a button. Or, study the submit_form method for which you can specify values of all the form elements. If the page uses javascript, WWW:Mechanize might be not suitable for your task (see for example WWW::Mechanize::Firefox for an alternative).
You need to use the select method. If you know the value (not the display-text), use this:
$agent->form_name("frmProject");
$agent->select('cboProject', $project);
my $response = $agent->submit();
If you don't take a look at the Mechanize FAQ. It says you have to do something like this:
# Find the correct input element
my ($projectlist) = $agent->find_all_inputs( name => 'cboProject' );
# Look up the value of the option
my %name_lookup;
#name_lookup{ $projectlist->value_names } = $projectlist->possible_values;
# use the display-text to get the correct value
my $value = $name_lookup{ $project };
Once you've done that, you can use the click-method to submit the page.
$agent->click_button('name_of_the_submit_button');
But if the button you have to click is the default action, $agent->submit() should do the trick as well.
Related
I'm beginner. I want to know how to fetch one table form the source HTML file using LWP module? Is it possible to use Regex with LWP?
You can use LWP to get the HTML source of a web page. Most easily, by using the get() function from LWP::Simple.
my $html = get('http://example.com/');
Now, in $html you have a text string (potentially a very long text string) which contains HTML. You can use any techniques you want to extract data from that string.
(Hint: Using a regex to do this is likely to be a very bad idea. It will be far harder than you expect and probably very fragile. Perhaps use a better tool - like HTML::TableExtract instead.)
use Web::Query::LibXML 'wq';
wq('https://www.december.com/html/demo/table.html')
->find('table th')
->each(sub {
my (undef, $e) = #_;
print $e->text . "\n";
});
__END__
Outer Table
Inner Table
CORNER
Head1
Head2
Head3
Head4
Head5
Head6
Little
i want to write a little script to grab and play around with the results of the autocomplete of an input field.
So I find a principal solution with Selenium::Firefox, that base on module Selenium::Remote::Driver, but the description of the methods is without any examples.
I have this basic example, that is able to open google and insert a search string.
Then you can see that a result list is suggested and i want to get this list.
But i have no idea how this can be obtained?
Here is my code so far:
#!/usr/bin/perl
use strict;
use warnings;
use Selenium::Firefox;
my $mech = Selenium::Firefox->new(
startup_timeout => 20,
firefox_binary => '/srv/bin/firefox.62.0/firefox',
binary => '/usr/local/bin/geckodriver',
marionette_enabled => 1
);
my $search = "perl";
my $url = "https://www.google.com/";
$mech->get($url);
$mech->find_element_by_name("q");
sleep(3);
my $result = $mech->get_active_element();
$result->send_keys($search);
sleep (10);
$mech->shutdown_binary;
exit 0;
I could find no examples to use this Perl module - and there are more questions for it.
As for instance: find_element
How can i turn on the warnings instead of killing the script?
Or how can i step through the objects of the wep page?
Is it possible to connect to an already opened browser?
The description of the module is not understandable for people who are not experts and the authors did not answer to questions so far.
But my hope is that experts here can give me a hint?
I am using the LWP::UserAgent,
HTML::Selector::XPath and
HTML::TreeBuilder::XPath modules to get the value of the href attribute of the first YouTube video in a set of search results.
My code so far is:
use LWP::UserAgent;
use HTML::TreeBuilder::XPath;
use HTML::Selector::XPath;
my $ua = LWP::UserAgent->new;
#my $response =..
my $html = "http://www.youtube.com/results?search_query=run+flo+rida";
my $tree = HTML::TreeBuilder::XPath->new;
my $xpath = HTML::Selector::XPath::selector_to_xpath("(//*[#id = 'search-results']/li)[1]/div[2]/h3/a/#href/");
my #nodes = $tree->findnodes($xpath);
print" $nodes[0]";
I'm not sure if my printing is incorrect of if some other syntax is wrong. As of now it prints
HTML::TreeBuilder::XPath=HASH(0x1a78250)
when I am looking for it to print
/watch?v=JP68g3SYObU
Thanks for any help!
There are a number of problems here.
You must always use strict and use warnings at the top of every Perl program. It will catch many errors that you would easily overlook, and is only polite when you are asking for help with your code. In this case it would have warned you that your XPath string contained array variable names #id and #href which you may not have intended to be interpolated into the string.
You are using HTML::Selector::XPath, which translates a CSS selector to an XPath expression. But you are supplying it an XPath expression, so it will not work and the module is not needed.
There is no need to use LWP at all, as HTML::TreeBuilder has a new_from_url constructor which will fetch the HTML page for you.
This program seems to do what you need. I have also added the URI module to derive an absolute URL from the relative one in the href attribute value.
use strict;
use warnings;
use HTML::TreeBuilder::XPath;
use URI;
my $url = "http://www.youtube.com/results?search_query=run+flo+rida";
my $tree = HTML::TreeBuilder::XPath->new_from_url($url);
my $anchor = $tree->findnodes('//ol[#id="search-results"]//h3[#class="yt-lockup2-title"]/a/#href');
my $href = URI->new_abs($anchor->[0]->getValue, $url);
print $href;
output
http://www.youtube.com/watch?v=JP68g3SYObU
I've been trying to read up on how to implement a JSON solution in order to use JQueryUI's autocomplete functionality. I am trying to use autocomplete to search a database on for a name and after selection populate the ID to a hidden object. I've seen alot of examples around the web, but haven't found the best way to implement this. The database doesn't change that often, so I'm not sure how to best approach this performance wise.
Backend:
#!/usr/bin/perl
use CGI;
use DBI;
use strict;
use warnings;
my $cgi = CGI->new;
my $dbh = DBI->connect('dbi:mysql:hostname=localhost;database=test',"test","test") or die $DBI::errstr;
my $sth = $dbh->prepare(qq{select id, name from test;}) or die
$dbh->errstr;
$sth->execute() or die $sth->errstr;
my $json = undef;
while(my #user = $sth->fetchrow_array()) {
$json .= qq{{"$user[0]" : "$user[1]"}};
}
print $cgi->header(-type => "application/json", -charset => "utf-8");
print $json;
The jQuery autocomplete needs a "value" or "label" field returned with the json result. If you do not include it, the jquery autocomplete will not work:
The basic functionality of the autocomplete works with the results of the query assigned to the ‘label’ and ‘value’ fields. Explanation on the ‘label’ and ‘value’ fields from the jQuery UI site:
“The local data can be a simple Array of Strings, or it contains Objects for each item in the array, with either a label or value property or both. The label property is displayed in the suggestion menu. The value will be inserted into the input element after the user selected something from the menu. If just one property is specified, it will be used for both, eg. if you provide only value-properties, the value will also be used as the label.”
Link to full example: http://www.jensbits.com/2011/05/09/jquery-ui-autocomplete-widget-with-perl-and-mysql/
You need to grap the JSON package from CPAN instead of doing this:
my $json = undef;
while(my #user = $sth->fetchrow_array()) {
$json .= qq{{"$user[0]" : "$user[1]"}};
}
For example, with JSON it'd look like this:
use JSON;
my $json = {};
while(my #user = $sth->fetchrow_array()) {
$json->{$user[0]} = $user[1];
}
print JSON::to_json($json);
The JSON package will automatically construct a valid JSON string from any Perl data structure you provide it. We use it all over the place on Melody and it's proved to be a real life saver for sanely converting a structure into valid JSON.
Here I'm talking about performance.
There is some trigger you can set to improve performance, client side you can set the minimum number of characters required before the request is sent.
You can also set the "timeout" between two characters typing before the request is sent.
If your database table is really huge, I suggest you put a LIMIT on results you retrieve.
First to avoid long request processing, but also because some clients like IE6 arent't really fast handling more than a hundred results (Not to say, it's also not really user friendly).
On a project using IE6, we limited the elements returned to 100. If the user can't reduce the search to 100 elements, we presume he/she doesn't know what he/she is looking for.
Hope it helps a bit.
I would like to write a script that lets me use this website
http://proteinmodel.org/AS2TS/LGA/lga.html
(I need to use it a few hundred times, and I don't feel like doing that manually)
I have searched the internet for ways how this could be done using Perl, and I came across WWW::Mechanize, which seemed to be just what I was looking for. But now I have discovered that the form on that website which I want to use has no name - its declaration line simply reads
<FORM METHOD="POST" ACTION="./lga-form.cgi" ENCTYPE=multipart/form-data>
At first I tried simply not setting my WWW::Mechanize object's form_name property, which gave me this error message when I provided a value for the form's email address field:
Argument "my_email#address.com" isn't numeric in numeric gt (>) at /usr/share/perl5/WWW/Mechanize.pm line 1618.
I then tried setting form_name to '' and later ' ', but it was to no avail, I simply got this message:
There is no form named " " at ./automate_LGA.pl line 40
What way is there to deal with forms that have no names? It would be most helpful if someone on here could answer this question - even if the answer points away from using WWW::Mechanize, as I just want to get the job done, (more or less) no matter how.
Thanks a lot in advance!
An easy and more robust way is to use the $mech->form_with_fields() method from WWW::Mechanize to select the form you want based on the fields it contains.
Easier still, use the submit_form method with the with_fields option.
For instance, to locate a form which has fields named 'username' and 'password', complete them and submit the form, it's as easy as:
$mech->submit_form(
with_fields => { username => $username, password => $password }
);
Doing it this way has the advantage that if they shuffle their HTML around, changing the order of the forms in the HTML, or adding a new form before the one you're interested in, your code will continue to work.
I don't know about WWW::Mechanize, but its Python equivalent, mechanize, gives you an array of forms that you can iterate even if you don't know their names.
Example (taken from its homepage):
import mechanize
br = mechanize.Browser()
br.open("http://www.example.com/")
for form in br.forms():
print form
EDIT: searching in the docs of WWW::Mechanize I found the $mech->forms() method, that could be what you need. But since I don't know perl or WWW::Mechanize, I'll leave there my python answer.
Okay, I have found the answer. I can address the nameless form by its number (there's just one form on the webpage, so I guessed it would be number 1, and it worked). Here's part of my code:
my $lga = WWW::Mechanize->new();
my $address = 'my_email#address.com';
my $options = '-3 -o0 -d:4.0';
my $pdb_2 = "${pdb_id}_1 ${pdb_id}_2";
$lga->get('http://proteinmodel.org/AS2TS/LGA/lga.html');
$lga->success or die "LGA GET fail\n";
$lga->form_number(1);
$lga->field('Address', $address);
$lga->field('Options', $options);
$lga->field('PDB_2', $pdb_2);
$lga->submit();
$lga->success or die "LGA POST fail\n";