Select dropdown option and submit form - python-requests

I have written code to get tables from a website, but I need to get access to an additional table by:
selecting a time frame from a dropdown.
submitting by clicking a 'filter' button.
The website is:
http://www.myfxbook.com/forex-market/currencies/nzdchf-historical-data
Inspect element on the dropdown shows this:
<select id="timeScales" class="selectField" onfocus="borderChange(this); "onblur="borderReturn(this);" style="border: 1px solid rgb(226, 225, 225);">
<option id="timeScale1" value="1">1 Minute</option>
<option id="timeScale5" value="5">5 Minutes</option>
<option id="timeScale15" value="15">15 Minutes</option>
<option id="timeScale30" value="30">30 Minutes</option>
<option id="timeScale60" value="60">1 Hour</option>
<option id="timeScale240" value="240">4 Hours</option>
<option id="timeScale1440" value="1440" selected="">1 Day</option>
<option id="timeScale10080" value="10080">1 Week</option>
<option id="timeScale43200" value="43200">1 Month</option>
From the timeframe dropdown, I want to select 4 hours, then click on the filter button.
I know how to get HTML using the requests.get method, but the problem I am having here is that the URL does not change when I select a dropdown value.
I have tried using requests.post, but I clearly don't know how to use it.
I am writing this program using "HOW TO AUTOMATE THE BORING STUFF USING PYTHON" as a tutorial, and the author does not explain how to programmatically click dropdown menus and click buttons.
He does explain the use of Selenium, but I have to repeat this process over 30 times, and having to open a new page every time would take too long.
I'd appreciate it if you could show how this could be achieved using requests module (if possible).

You cannot click a button with requests, what you can do is mimic requests that get the data, when you choose a time period click filter an ajax request is made:
So to mimic that and get the html we need to pass the params below:
import requests
params = {"start": "2016-02-02 00:00",
"end": "2016-06-20 00:00",
"symbol": "NZDCHF",
"timeScale": "240",
"userTimeFormat": "0"}
head = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36",
"X-Requested-With": "XMLHttpRequest"}
url = "http://www.myfxbook.com/getHistoricalDataByDate.json"
js = requests.get(url, params=params, headers=head).json()
Then to get the table, access js["content"]["historyData"]:
print(js["content"]["historyData"])
Which gives you the table:
<table id="symbolMarket" class="sortable maxWidth center dataTable">
<tr style="height:26px">
<th sort="string">
<a class="dotted font11 pointer">Date</a><span id="symbolMarketImg0"></span>
</th>
<th><span class="font11">Open</span></th>
<th><span class="font11">High</span></th>
<th><span class="font11">Low</span></th>
<th width="63"><span class="font11">Close</span></th>
<th sort="float" >
<a class="dotted font11 pointer">Change (Pips)</a><span id="symbolMarketImg5"></span>
</th>
<th sort="float" >
<a class="dotted font11 pointer">Change (%)</a><span id="symbolMarketImg6"></span>
</th>
</tr>
<tr onmouseover="this.className='normalActive';" onmouseout="this.className='';">
<td><span name="timeNZDCHF">Jun 20, 2016 00:00</span></td>
<td><span name="openNZDCHF">0.67771</span></td>
<td><span name="highNZDCHF">0.68133</span></td>
<td><span name="lowNZDCHF">0.67771</span></td>
<td><span name="closeNZDCHF">0.68057</span></td>
<td class="bold"><span name="changePipsNZDCHF"><span class='green'>+28.6</span></span></td>
<td class="bold"><span name="changePercentNZDCHF"><span class='green'>+0.42%</span></span></td>
</tr>
......................................
You could easily parse the original page to get the values from the tag using Beautifulsoup:
In [7]: from bs4 import BeautifulSoup
In [8]: h = """<select id="timeScales" class="selectField" onfocus="borderChange(this); "onblur="borderReturn(this);" style="border: 1px solid rgb(226, 225, 225);">
...: <option id="timeScale1" value="1">1 Minute</option>
...: <option id="timeScale5" value="5">5 Minutes</option>
...: <option id="timeScale15" value="15">15 Minutes</option>
...: <option id="timeScale30" value="30">30 Minutes</option>
...: <option id="timeScale60" value="60">1 Hour</option>
...: <option id="timeScale240" value="240">4 Hours</option>
...: <option id="timeScale1440" value="1440" selected="">1 Day</option>
...: <option id="timeScale10080" value="10080">1 Week</option>
...: <option id="timeScale43200" value="43200">1 Month</option>"""
In [9]: soup = BeautifulSoup(h,"html.parser")
In [10]: durations = ([opt["value"] for opt in soup.select("#timeScales option")])
In [11]: durations
Out[11]: [u'1', u'5', u'15', u'30', u'60', u'240', u'1440', u'10080', u'43200']
But I don't see the logic behind that as the durations are in minutes and you would need to know your duration for the data.

Related

Python select dropdown value with requests

Hello I have this simple html select options:
<select name="dnn$ctr6707$TimeTableView$ClassesList" id="dnn_ctr6707_TimeTableView_ClassesList" class="HeaderClasses">
<option selected="selected" value="14">ז1ש</option>
<option value="15">ז2ש</option>
<option value="16">ז3ש</option>
<option value="17">ז4ש</option>
<option value="49">ז5ש</option>
<option value="60">ז6ש</option>
<option value="24">ז7ש</option>
<option value="1">ז8ד</option>
<option value="2">ז9ד</option>
<option value="3">ז10ד</option>
<option value="4">ז11ד</option>
<option value="5">ח1ד</option>
<option value="6">ח2ד</option>
<option value="7">ח3ד</option>
<option value="8">ח4ד</option>
<option value="999">ח5ד</option>
<option value="18">ח6ש</option>
<option value="19">ח7ש</option>
<option value="20">ח8ש</option>
</select></td>
The form data for the table is ""dnn$ctr6707$TimeTableView$ClassesList"" However when i Get request it, The value of the class table doesn't change it stays on 14.
This is the website if you want to try: http://tikah.iscool.co.il/default.aspx
If you can provide me with get request that changes the value or explain (better with code) i will appreciate it!
Thanks!
Here's my code:
def main():
dat = {
'__EVENTTARGET': 'dnn_ctr6707_TimeTableView_TdChangesTable',
'__VIEWSTATEGENERATOR': 'CA0B0334',
'dnn$ctr6707$TimeTableView$ClassesList': 42,
'dnn$ctr6707$TimeTableView$ControlId': 2
}
responde = requests.get('http://tikah.iscool.co.il/default.aspx', data=dat)
This gets me a status code of 200, so i assume you can get whatever info you need from there.
import requests
from bs4 import BeautifulSoup as bs
url=r'http://tikah.iscool.co.il/default.aspx'
s=requests.Session()
r=s.get(url)
soup=bs(r.text,'html.parser')
dataload={
'__EVENTTARGET': 'dnn$ctr6707$TimeTableView$ClassesList',
'__EVENTARGUMENT': '',
'__LASTFOCUS': '',
'__VIEWSTATE': soup.find('input',{'id':'__VIEWSTATE'}).attrs['value'],
'__VIEWSTATEGENERATOR': soup.find('input',{'id':'__VIEWSTATEGENERATOR'}).attrs['value'],
'dnn$ctr6707$TimeTableView$ClassesList': '42',
'dnn$ctr6707$TimeTableView$ControlId': '',
'ScrollTop':'' ,
'__dnnVariable': ''
}
headers={
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.9',
'cache-control': 'max-age=0',
'content-length': '3278',
'Host': 'tikah.iscool.co.il',
'Origin': 'http://tikah.iscool.co.il',
'Referer': 'http://tikah.iscool.co.il/default.aspx',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36'
}
r=s.post(r.url,headers=headers,data=dataload)
print(r.status_code)
Explanation:
When i inspected the post request, i saw that there were some parameters getting passed that were unique to every browsing session (__VIEWSTATE and __VIEWSTATEGENERATOR in this case). So these values have to come from somewhere. I inspected the elements in the page and found the hidden inputs like this
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUIMjU3MTQzOTcPZBYGZg8WAh4EVGV4dAU+PCF........
So then it was just a matter of using BeautifulSoup to parse out the 'value' attribute and putting that in my dataload dict. If you haven't used BS before, i'd recommend reading the docs here

Firefox incorrectly displays items when loading a mvc razor page, select2 js

Firefox 59.0 Project MVC.NET. Use https://select2.github.io js lib for select elements
On the View there are many elements such as:
<div class="control control_medium control_select">
<select name="#nameof(Model.Query.BudgetCycleIds)"
#Html.AjaxViewSubmitOnChange()
#Html.AsugfAutoComplete()
multiple="multiple">
<option value="0">Все</option>
#foreach (var budgetCycle in Model.BudgetCycles)
{
<option value="#budgetCycle.Id" #(Model.Query.BudgetCycleIds?.Contains(budgetCycle.Id) ?? false ? "selected" : "")>#budgetCycle.Name</option>
}
</select>
</div>
Same in the html:
<select name="BudgetCycleIds" ajaxview-submit-onchange="" asugf-select2="" multiple="" tabindex="-1" class="select2-hidden-accessible" aria-hidden="true">
<option value="0">Все</option>
<option value="13" selected="">2010 - 2012</option>
<option value="14">2011 - 2013</option>
<option value="9">2012 - 2014</option>
<option value="5">2013 - 2015</option>
<option value="6">2014 - 2016</option>
<option value="7">2015 - 2017</option>
<option value="1">2016 - 2018</option>
<option value="2">2017 - 2019</option>
<option value="4">2018 - 2020</option>
</select>
Normal UI (before loading):
Not normal UI (in a second after loading):
Normal UI (in two second after loading):
The other browsers are the same, but very fast, and the user does not see the interface jumps.
How to make sure that the wrong interface does not appear
Not a good solution (because the layout is "jumps")
add hidden class
<option class="hidden" value="0">Все</option>
#foreach (var budgetCycle in Model.BudgetCycles)
{
<option class="hidden" value="#budgetCycle.Id" #(Model.Query.BudgetCycleIds?.Contains(budgetCycle.Id) ?? false ? "selected" : "")>#budgetCycle.Name</option>
}

I want to get phones data to drop-down list in Meteor

I want to get phones data to drop-down list in Meteor.I am using Mongodb.I tried something but it doesnt work
phones.js
Template.Phones.helpers({
getPhones: function(){
return Phone.find({});
}
});
show.html
<select class="form-control" name="aracsec" size="1" style="height:40px; width:290px; float:right" id="aracsec">
{{#each getPhones}}
<option value="{{userphone}}">{{userphone}}</option>
{{/each}}
</select>

please tell me how can i access value of gridview's cell in javascript

i have a gridview witch contain 4 databound columns and 2 templated column. in one of template column i placed a dropdownlist(witch contain number of items). and 2nd column of gridview contains prices. so in last column i want that when i select value in dropdownlist that value should multiply with 2nd column's value of datagrid and place result in last column of gridview using java script.
please tell me what to do..
You can get the row and column cell data using javascript. Here is a nice article on
Traversing an HTML table with JavaScript and DOM Interfaces
Also take a look at table.rows
Sample Code
HTML
<table>
<tr>
<td>
100
</td>
<td>
<select id="sel1" onchange="GetRowInd(this);">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</td>
<td></td>
</tr>
<tr>
<td>
100
</td>
<td>
<select id="sel2" onchange="GetRowInd(this);">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</td>
<td>
</td>
</tr>
</table>
javascript
function GetRowInd(selectbox)
{
var parentTr = selectbox.parentNode.parentNode;
var secondCellVal = parseInt ( parentTr.cells[0].innerText , 10 );
var comboVal = parseInt ( selectbox.value , 10 );
parentTr.cells[2].innerText = secondCellVal * comboVal;
}
You have to use textContent instead of innerText to work in FF.
jQuery solution
Remove the onchange event from the combo box and use the following function
$(function() {
$(".selectbox").change ( function() {
var comboVal = $(this).val();
var parentTr = $(this).parents('tr');
var tdElem = parentTr.children('td');
var secondCellVal = tdElem.eq('0').text();
tdElem.eq('2').text ( comboVal * secondCellVal );
});
});
You should be using ClientID property of the serverside controls and document.getElementById method to access your controls using javascript.
You may find this article helpful for generating neat ClientIDs.
This forum discussion may also show you the right way out.
Upd.:
Sample html:
<table>
<tr>
<td>cellValue</td>
<td><span id="comboId">combo</span></td>
</tr>
</table>
Sample javasricpt:
// alerts "cellValue"
alert(document.getElementById("comboId").parentNode.parentNode.cells[0].innerHTML);

ASP.NET Ajax Toolkit Watermark control issue & Javascript date question

I have a web page that uses three controls to allow a user to specify a date: 2 drop down controls for month and day (where Jan = 1, perhaps a bad choice :-)) and the days of the month (1-31). A text box is used for the year. In the Year text box, I use an AJAX Toolkit Watermark extender found [here][1] to write the literal word "Year" in light grey in the text box. This text disappears when the user sets focus to the text box. If the user enters something in the text box, the text appears in the normal textbox color, else the light grey text "Year" re-appears when the textbox loses focus.
3 control make up a "Date Issued" text box and similarly, 3 more control make up a "Expiration Date" set of controls.
When a user changes the Issue date (for example, the focus of the last control, Issued Year, is lost, I'd like to update the Expiration Date controls to a date value that is 10 years from the Issue date.
The issue is this: If I use Javascript to set the value of the txtExpireYear control, it updates the light grey text watermark text that normally says "Year" to the year number value instead of displaying the value in normal text color and treating the value as if it were typed by the user.
The 2nd issue that I have is getting the year value of the IssueDate. Why does the dtmDateOfIssue.getYear() function return a two-digit year if the year is <2000 and itherwise return a 4-digit year if the year is > 2000? I can probably work around this but I am looking for an explanation.
Thanks in advance.
function txtIssueYear_OnBlur() {
//Get sub controls of passport Expiration date
var ddlExpireMonth = document.getElementById("dtmPassportExpirationDate_ddlMonth");
var ddlExpireDate = document.getElementById("dtmPassportExpirationDate_ddlDate");
var txtExpireYear = document.getElementById("dtmPassportExpirationDate_txtYear");
//Get the individual values of each sub control of the Expiration date
var ExpireMonth = parseInt(ddlExpireMonth.value);
var ExpireDayOfMonth = parseInt(ddlExpireDate.value);
var ExpireYear = parseInt(txtExpireYear.value);
//If the Expiration Date still contains all the default values, set it to a default
//value based on the value of the Date of Issue
if ( ExpireMonth == -1 && ExpireDayOfMonth == -1 && (isNaN(ExpireYear)) ) {
//Get sub controls of passport Issue date
var ddlIssueMonth = document.getElementById("dtmPassportDateOfIssue_ddlMonth");
var ddlIssueDate = document.getElementById("dtmPassportDateOfIssue_ddlDate");
var txtIssueYear = document.getElementById("dtmPassportDateOfIssue_txtYear");
//Get the individual values of each sub control of the Issue date
var IssueMonth = parseInt(ddlIssueMonth.value);
var IssueDayOfMonth = parseInt(ddlIssueDate.value);
var IssueYear = parseInt(txtIssueYear.value);
var dtmDateOfIssue = new Date(IssueYear, IssueMonth - 1, IssueDayOfMonth); //construct Issue date
//add 10 years - 1 day to get the default Expiration date
dtmDateOfIssue.setYear(dtmDateOfIssue.getYear() + 10);
dtmDateOfIssue.setDate(dtmDateOfIssue.getDate() - 1);
//Set the Expiration Date
txtExpireYear.value = dtmDateOfIssue.getYear();
ddlExpireMonth.value = dtmDateOfIssue.getMonth() + 1;
ddlExpireDate.value = dtmDateOfIssue.getDate();
}
The 3 controls of each date group are included in a usercontrol (ASCX file):
<asp:DropDownList ID="ddlMonth" runat="server">
</asp:DropDownList>
<asp:DropDownList ID="ddlDate" runat="server">
</asp:DropDownList>
<asp:TextBox ID="txtYear" runat="server" Width="85px" ></asp:TextBox>
<asp:CustomValidator ID="CustomValidator1" runat="server"
EnableClientScript="true" Required="True"
ErrorMessage="CustomValidator" ClientValidationFunction="validateDate"
ValidateEmptyText="True"></asp:CustomValidator>
This is sent to the browser as the following. Note that the event handler that I am writing Javascript for uses the client side IDs because the client sided script is page-specific. Not sure if that will be clear or will make sense to you. I would prefer an example using the final client side names, but if you again want to offer the <%- servercontrol.ClientId %> approach too, I would be willing to give it a try.
THANK YOU!
<select name="dtmPassportExpirationDate$ddlMonth" id="dtmPassportExpirationDate_ddlMonth" class="DefaultDropDown">
<option value="-1">--Month--</option>
<option value="1">Jan</option>
<option value="2">Feb</option>
<option value="3">Mar</option>
<option value="4">Apr</option>
<option value="5">May</option>
<option value="6">Jun</option>
<option value="7">Jul</option>
<option value="8">Aug</option>
<option selected="selected" value="9">Sep</option>
<option value="10">Oct</option>
<option value="11">Nov</option>
<option value="12">Dec</option>
<select name="dtmPassportExpirationDate$ddlDate" id="dtmPassportExpirationDate_ddlDate" class="DefaultDropDown">
<option value="-1">--Day--</option>
<option value="1">1</option>
<option value="2">2</option>
<option selected="selected" value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="28">28</option>
<option value="29">29</option>
<option value="30">30</option>
<option value="31">31</option>
<input name="dtmPassportExpirationDate$txtYear" type="text" value="2009" maxlength="4" id="dtmPassportExpirationDate_txtYear" class="DefaultTextBox" style="width:68px;" />
<input name="dtmPassportExpirationDate$btnClear" type="button" id="dtmPassportExpirationDate_btnClear" style="font-size: x-small; height: 20px;" value="Clear" tabindex="-1" onClick="ClearDate_dtmPassportExpirationDate();" /></td>
<input type="hidden" name="dtmPassportExpirationDate$TextBoxWatermarkExtender1_ClientState" id="dtmPassportExpirationDate_TextBoxWatermarkExtender1_ClientState" />
About your second issue, the getYear function is deprecated, you should use the getFullYear function instead.
Edit: To correctly set the value of a TextBoxWatermark extended control, you should use the MS Ajax $find function to get the object and call the set_Text function:
$find("ctl00_SampleContent_TextBoxWatermarkExtender2").set_Text('value');
or better using the server-side ClientID property of the control:
$find("<%=ExtenderControl.ClientID%>").set_Text('value');
I found the set_Text function by object inspection with Firebug, because it's a shame that there is no documentation of the Client-Side API of the Ajax Control Toolkit...

Resources