Python select dropdown value with requests - python-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

Related

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>
}

How to match payload in POST request

I've got a GET request like this:
<FORM action='vieweto0.php' method='POST'>
<SELECT name='ID_Profil'>
<OPTION value=3> blank3</OPTION>
<OPTION value=2> blank2</OPTION>
<OPTION value=4>blank4</OPTION>
</SELECT>
<br><input type='submit' type=hidden name='OK' value='choose this one'>
</FORM>
How my POST request should look like if I want to choose OPTION 'blank4'?
Where I can read more about POST request like this?
If you use python requests:
import requests
res = requests.post("http://hostaddress/vieweto0.php", data={"ID_Profil":4})
POST or GET requests are basically sending key-value pairs to the server.
Learn more about http POST on https://www.w3schools.com/html/default.asp and how requests work on this: http://docs.python-requests.org/en/master/user/quickstart/. If you are interested in the details of POST, you can read this: https://www.rfc-editor.org/rfc/rfc7231#section-4.3.3.
You can use this $_POST['ID_Profil'];

Symfony2 form_widget datetime : an hour without leading zeros

formType
->add("someday", DateTimeType::class, [
"date_widget" => "single_text",
"minutes" => ["00", "20", "40"],
"required" => true,
])
template
{{ form_widget(form.someday.date) }}
{{ form_widget(form.someday.hour) }}
{{ form_widget(form.someday.minute) }}
Generated HTML (on hour part)
<select id="form_someday_time_hour" name="form[someday][time][hour]">
<option value="0">00</option>
<option value="1">01</option>
<option value="2">02</option>
<option value="3">03</option>
<option value="4">04</option>
<option value="5">05</option>
<option value="6">06</option>
<option value="7">07</option>
<option value="8">08</option>
<option value="9">09</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13" selected="selected">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>
</select>
In this case, selectbox of hour with leading zeros(00, 01, 02 ... 23),
but I would like to change this selectbox without leading zeros(0, 1, 2 ... 23).
I would like to generate HTML of this format. (on hour part)
<select id="form_someday_time_hour" name="form[someday][time][hour]">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option 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" selected="selected">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>
</select>
I tried specifying the format in the form type, but there was no change.
Will there be options for the widget on the template side?
Thank you if you know.
Try the Twig date filter and specify the hour format without leading zeros like so:
{{ form_widget(form.someday.hour|date('h')) }}
Formats are specified using the DateInterval.format. I think that should work for you. Please try it.
EDIT #2
I'm not sure why you are getting that error. Maybe it's because the date filter is in the wrong place? Can you try this:
{{ form_widget(form.someday.hour)|date('h') }}
I'm not sure if that will fix it, but please try it. If that doesn't work, maybe you can tell me how you want the "date", "hour" and "minute" to be rendered in HTML format (update your question post to show that); then maybe we can use the formatting of the DateTimeType field.
EDIT #3
Why not try this then:
$hours = new array();
for ($i = 0; $i <= 23; $i++) {
array_push($hours, strval($i));
}
...
->add("someday", DateTimeType::class, [
"date_widget" => "single_text",
"minutes" => ["00", "20", "40"],
"hours" => $hours,
"required" => true,
])
I think that will work for you.
EDIT #4
Try this as well.
->add("someday", DateTimeType::class, [
"format" => "dd H mm",
"minutes" => ["00", "20", "40"],
"required" => true,
])
Then will be shown as drop down lists. Not sure why you were using date_widget???
Unfortunately, that's impossible.
https://github.com/symfony/symfony/blob/f7d9701cdfaf9be6b40f661d0d9ec973dc4b904b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php#L74
Looking at the code, recognized added leading zeros here.
If rewrite like this, it may be the expected behavior.
- $hours[str_pad($hour, 2, '0', STR_PAD_LEFT)] = $hour;
+ $hours[$hour] = $hour;

Select dropdown option and submit form

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.

Html DropDownList helper does not select default value

I am trying to create a dropdownlist of months, that renders with the current month selected:
#Html.DropDownList("Month",
new SelectList(Enumerable.Range(1, 12).ToDictionary<int, string>(
i => System.Threading.Thread.CurrentThread.CurrentUICulture.DateTimeFormat.GetMonthName(i)
), "Value", "Key", DateTime.Now.Month));
This builds the list just fine, but it always renders with January selected.
What am I doing wrong here?
HTML output:
<select name="Info.Month" id="dLMonth-451" data-val-required="The Month field is required." data-val-number="The field Month must be a number." data-val="true">
<option value="1">January</option>
<option value="2">February</option>
<option value="3">March</option>
<option value="4">April</option>
<option value="5">May</option>
<option value="6">June</option>
<option value="7">July</option>
<option value="8">August</option>
<option value="9">September</option>
<option value="10">October</option>
<option value="11">November</option>
<option value="12">December</option>
</select>
Code works for me on MVC4/.Net 4. What version of .Net and MVC are you using?
could add some of the HTML output?

Resources