XPATH, Select an specific valid value from a Flex container - python

As the title implies I'm currently facing some issues trying to sort this out, the thing is I have an horizontal flex container which shows the Qtrs/Years in order to assign a valid one to a Package Rotation as you'll see on the bottom snippet there are 3 types of "status/classes" that I have to consider, given that certain quarters/years can be set as "Not valid" meaning I shouldn't consider them for the selection itself, leaving me to actually have to first search for the valid quarters (class="quarter valid and class="quarter valid selected, the latter one being the one I currently have selected duh')
Then after actually getting only the valid ones I need to be able to create an XPATH that allows me to travel through those options and be able to select them with an Index or preferably by text (eg: quarterNumber = '3Q' and year = "2021")
Basically the html/dom for that part is this:
<div class="quartersContainer"</div>
<div class="quarter">
<div class="quarterNumber">1Q</div>
<div class="year">2021</div>
<div class="releasedIndicator"></div>
<div class="quarterbar-editing-mode"></div>
</div>
<div class="quarter">
<div class="quarterNumber">2Q</div>
<div class="year">2021</div>
<div class="releasedIndicator"></div>
<div class="quarterbar-editing-mode"></div>
</div>
<div class="quarter valid selected">
<div class="quarterNumber">3Q</div>
<div class="year">2021</div>
<div class="releasedIndicator"></div>
<div class="quarterbar-editing-mode"></div>
</div>
<div class="quarter valid">
<div class="quarterNumber">4Q</div>
<div class="year">2021</div>
<div class="releasedIndicator"></div>
<div class="quarterbar-editing-mode"></div>
</div>
<div class="quarter">
<div class="quarterNumber">1Q</div>
<div class="year">2022</div>
<div class="releasedIndicator"></div>
<div class="quarterbar-editing-mode"></div>
</div>
What I have so far is just this.... (I'm really new to this :( )
//div[contains(#class,'quarter valid') and .//#class='quarterNumber' and .//#class='year']
The whole point of this is to actually generate an XPATH that can be manipulated in a future or through a Behave Feature file for example so testers just have to actually change the text from something like 2Q - 2021 to 3Q - 2023 and it will be able to look for it.
Any advice or guidance would be greatly appreciated :')

Like #DMart is suggesting, do something like this
def build_xpath(year ,quarterNumber):
return "//div[contains(#class,'quarter valid') and .//#class='" + year = "' and .//#class='" + quarterNumber + "']"
And then it's up to you how and with with what values you call build_xpath()

Related

Loop through tags inside tags in Selenium/Python

I am trying to use selenium to loop through a list of properties on a web page and return the property address and auction time. I have the following python code so far and html for the web page below.
I'm able to return the links to every property in the list, but can't seen to return the values I need from the "H4" tags. I think I'm doing something wrong with getting the elements by Xpath but I can't seem to figure it out.
Any help would be greatly appreciated!
HTML:
<div data-elem-id="asset_list_content">
<a href="/details/123-memory-lane">
<div data-elm-id="asset_2352111_address" class="styles__address-container--2l39p styles__u-mr-1--3qZyj">
<h4 data-elm-id="asset_2352111_address_content_1" class="styles__asset-font-big--vQU7K">123 memory-lane</h4>
<label data-elm-id="asset_2352111_address_content_2" class="styles__asset-font-small--2JgrX">POWDER SPRINGS, GA 30127, Cobb County</label>
</div>
<div class="styles__auction-container--45DZU styles__u-ml-1--34mF_">
<h4 data-elm-id="asset_2352111_auction_date" class="styles__asset-font-big--vQU7K">Apr 04, 10:00am</h4>
</div>
</a>
<a href="/details/456-memory-lane">
<div data-elm-id="asset_8463157_address" class="styles__address-container--2l39p styles__u-mr-1--3qZyj">
<h4 data-elm-id="asset_8463157_address_content_1" class="styles__asset-font-big--vQU7K">456 memory-lane</h4>
<label data-elm-id="asset_8463157_address_content_2" class="styles__asset-font-small--2JgrX">POWDER SPRINGS, GA 30127, Cobb County</label>
</div>
<div class="styles__auction-container--45DZU styles__u-ml-1--34mF_">
<h4 data-elm-id="asset_8463157_auction_date" class="styles__asset-font-big--vQU7K">March 10, 10:00am</h4>
</div>
</a>
</div>
Python (Selenium):
propertyList = browser.find_elements_by_xpath('//div[#data-elm-id="asset_list_content"]')
for element in propertyList:
propertyLinks = element.find_elements_by_tag_name('a')
for propertyLink in propertyLinks:
propertyAddress = propertyLink.get_element_by_xpath('//h4[1]')
propertyAuctionTime = propertyLink.get_element_by_xpath('//h4[2]')
print(propertyAddress).text
print(propertyAuctionTime).text
Output:
propertyAddress = propertyLink.get_element_by_xpath('//h4[1]')
AttributeError: 'WebElement' object has no attribute 'get_element_by_xpath'
The error seems to be you are using get_element_by_xpath(), which isn't a valid method. You used find_elements_by_xpath() in your code before that moment, and to find the elements you are looking for you just need to use the method that only finds a single element: find_element_by_xpath().

Unable to get whole row from BeautifulSoup

I've been practicing my scraping and everything was going fine but as hard as I try I can't seem to get this specific data I'm looking for.
Structure looks like this
</div>
<div class="col-xs-12 col-sm-12 col-md-7 list-field-wrap">
<div class="pull-left">
<div class="row">
<div class=" list-field type-field" style="width: 45px"><div class="visible-xs-block visible-sm-block list-label">BIB</div>17584</div>
<div class=" list-field type-age_class" style="width: 65px"><div class="visible-xs-block visible-sm-block list-label">Division</div>20-24</div>
</div>
</div>
What I want to do is get the 17584 with class = "visible-xs-block visible-sm-block list-label"
Unfortunately every time I try to select it. It only returns
<div class="visible-xs-block visible-sm-block list-label">BIB</div>
This is my code I've been trying to select it
bib = soup.find('div', class_="visible-xs-block visible-sm-block list-label"
print(bib)
WAS ABLE TO FIGURE IT OUT STRUCTURE START EARLIER.
17584 is not part of the tag with class visible-xs-block visible-sm-block list-label:
<div class=" list-field type-field" style="width: 45px">
<div class="visible-xs-block visible-sm-block list-label">
BIB
</div>
17584
</div>
Try to select list-field type-field instead.

How to uniquely identify xpath for multiple tags and multiple values

I have following html:
<div class=‘content active’>
<div>
<div class=‘var’>
<div class=‘field var-field’>
<label>Interface Name</label>
<div class=‘ui input’>
<input type=‘input’ placeholder=‘.*’ value> ==$0
</div>
</div>
</div>
</div>
<div>
<div class=‘var’>
<div class=‘field var-field’>
<label>Neighbor Id</label>
<div class=‘ui input’>
<input type=‘input’ placeholder=‘.*’ value> ==$0
</div>
</div>
</div>
</div>
</div>
I need to send text to the text box with label: Interface Name.
Is there a way to uniquely write the xpath to send the text to the textbox.
Note that the only way to identify uniquely is wrt the label. The other fields in the tag is same for both.
I tried using AND operator. No luck.
Please help me out here.
Try this :
//label[text()='Interface Name']/following-sibling::div/child::input
To send text to the <input> element with respect to the <label> tag you can create a function as follows :
def test_me(myText):
driver.find_element_by_xpath("//label[.='" + myText + "']//following::div[1]/input").send_keys("hello")
Now, you can call this function from anywhere within your script as follows :
test_me("Interface Name")
# or
test_me("Neighbor Id")
You can use this XPATH :- //*[text()='Interface Name']/following-sibling::div/input"

bootstrap columns - page or containers?

I have a sidebar and main content, however, inside my main content i want to have 3 rows. The top row, will span the whole main content. The middle row has 3 columns equally spaced spanning the main content. The bottom row will have 2 equally spaced.
if my layout of content is
<div class="container-fluid">
<div class="row">
<div class="col-md-1 sidebar">
</div>
<div class="col-md-11 main-content">
</div>
</div>
</div>
my css has these spanning the height of 100% of the viewport, so inside the content for my rows i tried -
1. nesting another .container-fluid inside of the main-content and then do a new row for each the top, middle, and bottom row?
From my attempts, this did not work I believe due to me trying to nest a container inside another container. If I'm wrong and you can nest a container inside of another, does that container inside .main-content have 12 new columns? Or am i working off of the 11 columns the .main-content is already using?
My other attempt was -
2. going straight to a row (not nesting in another .container. But when i did this, i could not get the row to span the whole .main-content (even using the class="col-md-11"). so my middle row (second row which i wanted to be under the top row) was to the right of my first row. I tried adding .main-content {display: block} to make the rows on top of each other but this did not work either.
Did i approach this wrong? Should I not put the .sidebar and .main-content into the same .container-fluid?
<div class="container-fluid">
<div class="row">
<div class="col-md-1 sidebar"></div>
<div class="col-md-11 main-content">
<div class="row">
<div class="col-md-12"></div>
</div>
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-4"></div>
<div class="col-md-4"></div>
</div>
<div class="row">
<div class="col-md-6"></div>
<div class="col-md-6"></div>
</div>
</div>
</div>
</div>

Need help scraping items from a list with Scrapy using ancestor

I am trying to scrape the details like Contact, Location, Phone and Rate. The html is as below. The list is a dynamic one so sometimes only few of the items like Contact and Location may appear on the page while sometimes all of them can appear. I am thinking I can use the icon tag to get the required text but am unable to find any documentation on this. Any help would be highly appreciated.
Thanks in advance.
<div class="detail-all-label">
<i class="abc-Contact"></i>
<div class="detail-all-text"><b>Contact</b>: Ram Bahadur</div>
</div>
<div class="detail-all-label">
<i class="abc-font abc-Location"></i>
<div class="detail-all-text"><b>Location</b>: Kathmandu</div>
</div>
<div class="detail-all-label">
<i class="abc-font abc-Website"></i>
<div class="detail-all-text"><b>Website</b>: itworkremotely</div>
</div>
<div class="detail-all-label">
<i class="abc-font abc-Phone"></i>
<div class="detail-all-text"><b>Phone</b>: 3283550121</div>
</div>
<div class="detail-all-label">
<i class="abc-font abc-Rate"></i>
<div class="detail-all-text"><b>Rate</b>: €700 - 10000</div>
</div>
You can get all of the detail values that have a preceding b element inside the div with class="detail-all-text":
for detail in response.xpath("//div[#class='detail-all-text']/b"):
name = detail.xpath("text()").extract()[0]
value = detail.xpath("following-sibling::text()")[0]
print name, value

Categories

Resources