Get all text wrapped by THEN if condition - python

html code
<div class=media>
<div class=11></div>
<div class=22></div>
<div class=media-content>
yes, this is the text<BR>
that i want to compare below
multiple line
</div>
</div>
<div class=media>
<div class=11></div>
<div class=22></div>
<div class=media-content>
and i want to compare above text multiple line
then if both same, i wanna break the loop
But it is not work
</div>
</div>
Succeeded to select first element (was checked by chropath)
driver.find_elements_by_xpath('//div[#class="media"][last()]//div[#class="media-content"]')
Succeeded to select second element (was checked by chropath)
driver.find_elements_by_xpath('//div[#class="media"][last()-1]//div[#class="media-content"]')
But both text was NOT same but always TRUE then break.
if driver.find_elements_by_xpath('//div[#class="media"][last()]//div[#class="media-content"]').gettext() == driver.find_elements_by_xpath('//div[#class="media"][last()-1]//div[#class="media-content"]').gettext():
break
Yes, it is not work.
I wanna compare the text(multi line) in both first and second element(#class=media-content)
If both multi-lined text was same, i wanna stop the loop.
But both text was NOT same as you see, but always become TRUE then STOPPED(break)
I am succeed to select item (*with last[], last[]-1)
But i don't why it works wrong.....
Is there anybody to troubleshoot my newbie code?
//text(), .gettext(), .text()

Try the below code.
items1=[item.text for item in driver.find_elements_by_xpath('//div[#class="media"][last()-1]//div[#class="media-content"]')]
items2=[item.text for item in driver.find_elements_by_xpath('//div[#class="media"][last()]//div[#class="media-content"]')]
if items1==items2:
print("pass")
else:
print("fail")

For me anser is (in case if where are more then one div[#class="media-content"] elements in singal div[#class="media"] node):
media_last = driver.find_elements_by_xpath('//div[#class="media"][last()]//div[#class="media-content"]')
media_last = [a.gettext() for a in media_last]
media_not_last =driver.find_elements_by_xpath('//div[#class="media"][last()-1]//div[#class="media-content"]')
media_not_last = [a.gettext() for a in media_not_last]
if media_last == media_not_last:
break
you can't get method gettext at the array of elements
or if you want get jast a singl element use find_element_by_xpath method

I tested the following using your html and I get the behaviour you expect:
from selenium import webdriver
driver = webdriver.Chrome()
driver.get(r'file:///<path to local html file>') # Used local html file for testing purposes
el1 = driver.find_elements_by_xpath('//div[#class="media"][last()]//div[#class="media-content"]')
el2 = driver.find_elements_by_xpath('//div[#class="media"][last()-1]//div[#class="media-content"]')
if el1[0].text == el2[0].text:
print('Yes')
else:
print('No')
One thing to understand is that driver.find_elements_by_path() returns a list object. So even though it appears you are targeting specific elements in your page, they are stored in list objects and you should refer to them that way if you wish to access the text of the elements.

Related

How to use Python Flask variables in Javascript

I have a Python variable whose value is a string of text and would like to edit that value via Javascript.
I have no idea how to go about doing this.
Attempts:
function changeValue(val) {
val = 'new text';
}
<textarea placeholder="some text">{{ changeValue({{ result }}) }}</textarea>
<textarea placeholder="some text">
{{ result }}
</textarea>
What I want: I have some text (result) being added and would like to check if the text is empty. If so, I want to show the placeholder text.
The issue: Although I can check if the value is empty, when I try to print that result out it reads none
Thanks to all!
You do not need to call the JavaScript function from the HTML file. There are several approaches you can take:
1. Store the variable in HTML metadata:
<meta id="result_var" data-result={{result}}>
And then get the data in JavaScript:
result = document.getElementById("result_var").value;
2. Keep the variable in the tag where it's supposed to be and get it from there in JavaScript:
<textarea placeholder="some text" id="result-var"> {{result}} </textarea>
And then get it in JavaScript:
let result = document.getElementById("result-var");
3. Query it from your API: You can create a route in your Flask app that returns JSON data with the variable you need and then get that data to your JavaScript file by sending a request to your API.
4. Jinja format: I've seen solutions that involve just using the variable as if it was a jinja variable in JavaScript like this: let result = JSON.parse('{{ result | tojson }}');. But I haven't been able to get this working properly, not sure why.
I hope this helps!

How to fix HTML email numbered list causing tabs after list exceeds 99?

I have a Python script that uses smtplib, email.mime.multipart, and email.mime.text to send an email with a numbered list. After the list exceeds 99 it inserts tabs after the number and messes up the formatting.
The only thing that has worked so far has been inserting a line break after each number to keep formatting consistent, but it doesn't look as good.
for i in range(0:200):
body_row = '<li>First line here <br>Second line here</li>'
body_total += body_row
body_total = "Total List" + "<ol>" + body_total + "</ol>" + "<br>"
The output looks like this:
99. First line here
Second line here
100. First line here
Second line here
101. First line here
Second line here
Does anyone know of an easy way to fix this other than my line break solution?
Your question has little do with Python programming, as it is primarily about how to format something in HTML.
I think the answer is to use the HTML <ol> ordered list tag, which will do what you want (and you don't have to explicitly number the elements yourself).
<ol>
<li>
First line here<br />
Second line here
</li>
<li>
First line here<br />
Second line here
</li>
<li>
First line here<br />
Second line here
</li>
<li>
First line here<br />
Second line here
</li>
.
.
.
</ol>
Result rendered by a web browser:
An alternative way. My first attempt at python so go easy on me with this one.
print """<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tbody>"""
for x in range(0, 200):
rowData = """ <tr>
<td> %d</td>
<td>first line<br> second line</td>
</tr>""" % (x)
print rowData
print """ </tbody>
</table>"""
I used print to see how my table structure is, you can change these to variables. The structure above will ensure your numbers are right on all email clients and the columns will be the same across all as well. Below is a screenshot of how the output will look.

How to pass value from python to html form using flask/jinja

So I first create an array of all folders in a specific directory, I then pass that to my html file.
def test_yt_vid():
mylist = os.listdir(WD+r"static/"+YOUTUBE_FOLDER)
full_path = (WD+YOUTUBE_FOLDER)
return dict(mylist=mylist, full_path=full_path)
Next I look through that array to find what file has been selected.
<select name=list id="videolist" method="GET" action="/">
{% for mylist in mylist %}
<option value= "{{mylist}}" SELECTED>{{mylist}}</option>"
{% endfor %}
</select>
Next I use JS to get the specific value into a variable
$('#videolist').change(function () {
//console.log($("#videolist").val());
var fileInput = $("#videolist").val())};
So The problem is here, I'm not sure how I would go about passing that value into the following jinja code
<video id="videotesting1" class="video" width="300" height="240" autoplay loop controls="true">
<source src="{{url_for('static',filename='videoTest/' + 'testVid.mp4')}}" type="video/mp4">
</video >
I'm trying to replace 'testVid.mp4' with the variable fileInput from the JS, I tried using $("#videotesting1").attr("src","{{url_for('static',filename='videoTest/'" + fileInput +")}}");'
But no luck so far.
This is different to "How do you change video src using jQuery?" because I am trying to pass a jinja variable to HTML using js.
You have some wrong closed quotes. Take a look at filename, where you set 'videoTest/' plus some variable value (e.g x), which results in 'videoTest/'x. Do you notice it? The single quote closed after videoTest should appear after the variable fileInput. The correct way would be:
$("#videotesting1").attr("src","{{url_for('static',filename='videoTest/" + fileInput + "')}}");
When you modify the src, has by inspect element the src changed, but the desired video isn't being played? If so, try:
$("#videotesting1").load()
Take a look at what load does # JQuery docs.
Figure out the problem, the file name has to go outside the jinja code because it doesnt get rendered by jinja for some reason when the event happens.
$("#videotesting1").attr("src","{{url_for('static',filename='videoTest/')}}" + fileInput);

Python Selenium can't change Select element value

I have a Select element with two options: Credit / Debit Card and Cash, with the former being the default. I have tried everything conventional and whatever else I can think of but I cannot change this value to Cash. My code as it stands is the following
pay_type_dropdown = driver.find_element_by_xpath(path_ending_in_select)
pay_type_dropdown.click()
# Have tried with and without clicking. Never seemed to make a difference.
pay_type_select = Select(pay_type_dropdown)
pay_type_select.select_by_visible_text('Cash')
But I have also tried select_by_value('CASH') - the option tag's value - and select_by_index(1), as well as
pay_type_dropdown = driver.find_element_by_xpath(path_ending_in_select)
pay_type_dropdown.click()
elems = pay_type_dropdown.find_elements_by_tag_name('option')
elems[1].click()
and
elems = pay_type_dropdown.find_elements_by_xpath(path_ending_in_select + '/option')
elems[1].click()
also to no avail. The drop box opens (if clicked on with the click() function) but no other value is selected. Nothing happens past that and there is no error. It is not in a separate frame as I am able to interact with everything else without having to shift into the correct frame. Any help would be much appreciated, thanks.
EDIT: This is the relevant HTML.
<div class="z-form-row" data-bind="visible: settings.tender.active, 'if': settings.tender.active">
<div class="z-form-field">
<label data-bind="_t: 'cart_options_payment_label'">I'll pay with:</label>
<select data-bind="value: settings.tender.selected, options: settings.tender.types, optionsText: 'label',
optionsValue: 'id', valueAllowUnset: true"><option selected="selected" value="CARD">Credit / Debit Card</option><option value="CASH">Cash</option></select>
</div>
<i class="z-row-icon z-icon-card" data-bind="css: tenderTypeIcon()"></i>
</div>

Programmatically delete everything before a HTML node?

I am trying to create a corpus of data from a set of .html pages I have stored in a directory.
These HTML pages have lots of info I don't need.
This info is all stored before the line
<div class="channel">
How can I programmatically remove all of the text before
<div class="channel">
in every HTML file in a folder?
Bonus question for a 50point bounty :
How do I programmatically remove everything AFTER, for example,
<div class="footer">
?
So if my index.html was previously :
<head>
<title>This is bad HTML</title>
</head>
<body>
<h1> Remove me</h1>
<div class="channel">
<h1> This is the good data, keep me</h1>
<p> Keep this text </p>
</div>
<div class="footer">
<h1> Remove me, I am pointless</h1>
</div>
</body>
After my script runs, I want it to be :
<div class="channel">
<h1> This is the good data, keep me</h1>
<p> Keep this text </p>
</div>
This is a bit heavy on memory usage, but it works. Basically you open up the directory, get all ".html" files, read them into a variable, find the split point, store the before or after in a variable, and then overwrite the file.
There are probably better ways to do this, nonetheless, but it works.
import os
dir = os.listdir(".")
files = []
for file in dir:
if file[-5:] == '.html':
files.insert(0, file)
for fileName in files:
file = open(fileName)
content = file.read()
file.close()
loc = content.find('<div class="channel">')
newContent = content[loc:]
file = open(fileName, 'w')
file.write(newContent)
file.close()
If you wanted to just keep up to a point:
newContent = content[0:loc - 1] # I think the -1 is needed, not sure
Note that the things you're searching should be kept in a variable, and not hardcoded.
Also, this won't work recursively for file/folder structures, but you can find out how to modify it to do that very easily.
to remove everything above and everything below
that means the only thing left should be this section:
<div class="channel">
<h1> This is the good data, keep me</h1>
<p> Keep this text </p>
</div>
rather than thinking to remove the unwanted, it would be easier to just extract the wanted.
you can easily extract channel div using XML parser such as DOM
You've not mentioned a language in the question - the post is tagged with python so this answer might still be out of context, but I'll give a php solution that could likely easily be rewritten in another language.
$html='....'; // your page
$search='<div class="channel">';
$components = explode($search,$html); // [0 => before the string, 1 => after the string]
$result = $search.$components[1];
return $result;
To do the reverse is fairly easy too; simply take the value of $components[0] after altering $search to your <div class="footer"> value.
If you happen to have the $search string cropping up multiple times:
$html='....'; // your page
$search='<div class="channel">';
$components = explode($search,$html); // [0 => before the string, 1 => after the string]
unset($components[0]);
$result = $search.implode($search,$components);
return $result;
Someone who knows python better than I do feel free to rewrite and take the answer!

Categories