Python Selenium - get href value - python

I am trying to copy the href value from a website, and the html code looks like this:
<p class="sc-eYdvao kvdWiq">
<a href="https://www.iproperty.com.my/property/setia-eco-park/sale-
1653165/">Shah Alam Setia Eco Park, Setia Eco Park
</a>
</p>
I've tried driver.find_elements_by_css_selector(".sc-eYdvao.kvdWiq").get_attribute("href") but it returned 'list' object has no attribute 'get_attribute'. Using driver.find_element_by_css_selector(".sc-eYdvao.kvdWiq").get_attribute("href") returned None. But i cant use xpath because the website has like 20+ href which i need to copy all. Using xpath would only copy one.
If it helps, all the 20+ href are categorised under the same class which is sc-eYdvao kvdWiq.
Ultimately i would want to copy all the 20+ href and export them out to a csv file.
Appreciate any help possible.

You want driver.find_elements if more than one element. This will return a list. For the css selector you want to ensure you are selecting for those classes that have a child href
elems = driver.find_elements_by_css_selector(".sc-eYdvao.kvdWiq [href]")
links = [elem.get_attribute('href') for elem in elems]
You might also need a wait condition for presence of all elements located by css selector.
elems = WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".sc-eYdvao.kvdWiq [href]")))

As per the given HTML:
<p class="sc-eYdvao kvdWiq">
Shah Alam Setia Eco Park, Setia Eco Park
</p>
As the href attribute is within the <a> tag ideally you need to move deeper till the <a> node. So to extract the value of the href attribute you can use either of the following Locator Strategies:
Using css_selector:
print(driver.find_element_by_css_selector("p.sc-eYdvao.kvdWiq > a").get_attribute('href'))
Using xpath:
print(driver.find_element_by_xpath("//p[#class='sc-eYdvao kvdWiq']/a").get_attribute('href'))
If you want to extract all the values of the href attribute you need to use find_elements* instead:
Using css_selector:
print([my_elem.get_attribute("href") for my_elem in driver.find_elements_by_css_selector("p.sc-eYdvao.kvdWiq > a")])
Using xpath:
print([my_elem.get_attribute("href") for my_elem in driver.find_elements_by_xpath("//p[#class='sc-eYdvao kvdWiq']/a")])
Dynamic elements
However, if you observe the values of class attributes i.e. sc-eYdvao and kvdWiq ideally those are dynamic values. So to extract the href attribute you have to induce WebDriverWait for the visibility_of_element_located() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
print(WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "p.sc-eYdvao.kvdWiq > a"))).get_attribute('href'))
Using XPATH:
print(WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//p[#class='sc-eYdvao kvdWiq']/a"))).get_attribute('href'))
If you want to extract all the values of the href attribute you can use visibility_of_all_elements_located() instead:
Using CSS_SELECTOR:
print([my_elem.get_attribute("innerHTML") for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "p.sc-eYdvao.kvdWiq > a")))])
Using XPATH:
print([my_elem.get_attribute("innerHTML") for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//p[#class='sc-eYdvao kvdWiq']/a")))])
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

The XPATH
//p[#class='sc-eYdvao kvdWiq']/a
return the elements you are looking for.
Writing the data to CSV file is not related to the scraping challenge. Just try to look at examples and you will be able to do it.

To crawl any hyperlink or Href, proxycrwal API is ideal as it uses pre-built functions for fetching desired information. Just pip install the API and follow the code to get the required output. The second approach to fetch Href links using python selenium is to run the following code.
Source Code:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
import time
list = ['https://www.heliosholland.com/Ampullendoos-voor-63-ampullen','https://www.heliosholland.com/lege-testdozen’]
driver = webdriver.Chrome()
wait = WebDriverWait(driver,29)
for i in list:
driver.get(i)
image = wait.until(EC.visibility_of_element_located((By.XPATH,'/html/body/div[1]/div[3]/div[2]/div/div[2]/div/div/form/div[1]/div[1]/div/div/div/div[1]/div/img'))).get_attribute('src')
print(image)
To scrape the link, use .get_attribute(‘src’).

Get the whole element you want with driver.find_elements(By.XPATH, 'path').
To extract the href link use get_attribute('href').
Which gives,
driver.find_elements(By.XPATH, 'path').get_attribute('href')

try something like:
elems = driver.find_elements_by_xpath("//p[contains(#class, 'sc-eYdvao') and contains(#class='kvdWiq')]/a")
for elem in elems:
print elem.get_attribute['href']

Related

Getting text from a div + code object with Selenium

I'm trying to get the text inside these div's but I'm not succeeding. They have a code between the class that doesn't change with each execution.
<div data-v-a5b90146="" class="html-content"> Text to be captured</div>
<div data-v-a5b90146="" class="html-content"><b> TEXT WANTED </b><div><br></div>
I've tried with XPATH, but I was not successful too.
content = WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.XPATH, '/html/body/div/div/div/div/div/div/div[1]/div[2]/div[2]/div[4]/div/div/b'))).text
You need to change couple of things.
presence_of_all_elements_located() returns list of elements, so you can't use .text with a list. To get the text value of the element you need to iterate and then get the text.
xpath seems very fragile. you should use relative xpath since class name is unique you can use the classname.
your code should be like.
contents = WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.XPATH, '//div[#class="html-content"][#data-v-a5b90146]')))
for content in contents:
print(content.text)
You can use visibility_of_all_elements_located() as well
contents = WebDriverWait(driver, 10).until(EC.visibility_of_all_elements_located((By.XPATH, '//div[#class="html-content"][#data-v-a5b90146]')))
for content in contents:
print(content.text)
Both the <div> tags have the attribute class="html-content"
Solution
To extract the texts from the <div> tags instead of presence_of_all_elements_located(), you have to induce WebDriverWait for visibility_of_all_elements_located() and using list comprehension and you can use either of the following locator strategies:
Using CSS_SELECTOR:
print([my_elem.text for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "div.html-content")))])
Using XPATH:
print([my_elem.text for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//div[#class='html-content']")))])
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Try to get the element first then get the text from the element;
element = WebDriverWait(
driver,
10
).until(
EC.presence_of_all_elements_located((
By.XPATH, '/html/body/div/div/div/div/div/div/div[1]/div[2]/div[2]/div[4]/div/div/b'
))
)
content = element.text

Getting list of all the URLs in a Closed Issue page in GitHub using Selenium

I am trying to store the links of all the closed issues from a GitHub (https://github.com/mlpack/mlpack/issues?q=is%3Aissue+is%3Aclosed) project using Selenium. I use the code below:
repo_closed_url = [link.find_element(By.CLASS_NAME,'h4').get_attribute('href') for link in driver.find_elements(By.XPATH,'//div[#aria-label="Issues"]')]
However, the above code only returns the first URL. How can I get all the URLs in that page? I iterate through all the pages. So just getting the links from the first page is fine.
Please try this. This should work:
repo_closed_url = [link.get_attribute('href') for link in driver.find_elements(By.XPATH,"//div[#aria-label='Issues']//a[contains(#class,'h4')]")]
Here //div[#aria-label='Issues']//a[contains(#class,'h4')] XPath locates directly all the desired title elements on the page.
Then the rest of the code in the line is iterating over the list of returning elements extracting their href attributes as I explained in the previous question.
To extract the links from all the href attributes you have to induce WebDriverWait for visibility_of_all_elements_located() and you can use either of the following locator strategies:
Using CSS_SELECTOR:
driver.get("https://github.com/mlpack/mlpack/issues?q=is%3Aissue+is%3Aclosed")
print([my_elem.get_attribute("href") for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "div[id^='issue_'] a[id^='issue']")))])
Using XPATH:
driver.get("https://github.com/mlpack/mlpack/issues?q=is%3Aissue+is%3Aclosed")
print([my_elem.get_attribute("href") for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//div[starts-with(#id, 'issue_')]//a[starts-with(#id, 'issue')]")))])
Console Output:
['https://github.com/mlpack/mlpack/issues/3371', 'https://github.com/mlpack/mlpack/issues/3370', 'https://github.com/mlpack/mlpack/issues/3369', 'https://github.com/mlpack/mlpack/issues/3368', 'https://github.com/mlpack/mlpack/issues/3367', 'https://github.com/mlpack/mlpack/issues/3365', 'https://github.com/mlpack/mlpack/issues/3364', 'https://github.com/mlpack/mlpack/issues/3363', 'https://github.com/mlpack/mlpack/issues/3356', 'https://github.com/mlpack/mlpack/issues/3353', 'https://github.com/mlpack/mlpack/issues/3352', 'https://github.com/mlpack/mlpack/issues/3351', 'https://github.com/mlpack/mlpack/issues/3348', 'https://github.com/mlpack/mlpack/issues/3340', 'https://github.com/mlpack/mlpack/issues/3338', 'https://github.com/mlpack/mlpack/issues/3336', 'https://github.com/mlpack/mlpack/issues/3333', 'https://github.com/mlpack/mlpack/issues/3329', 'https://github.com/mlpack/mlpack/issues/3326', 'https://github.com/mlpack/mlpack/issues/3325', 'https://github.com/mlpack/mlpack/issues/3324', 'https://github.com/mlpack/mlpack/issues/3323', 'https://github.com/mlpack/mlpack/issues/3319', 'https://github.com/mlpack/mlpack/issues/3314', 'https://github.com/mlpack/mlpack/issues/3303']
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Try the below XPath expression:
//div[#aria-label='Issues']//a[contains(#id,'issue')]
This XPath expression will list all the closed issues in page 1. Just use .get_attribute('href') to get the URLs.

Extract list of text from g element within svg tag using Selenium and Python

I would like to extract the following text fields that are located within a g tag which is located in a svg tag (the url: https://www.msci.com/our-solutions/esg-investing/esg-ratings-climate-search-tool). I put in a company name and search for it, expand the last drop down menu and want to extract information from the <svg>.
HTML Part I:
HTML Part II:
I tried what has been suggested here: Extracting text from svg using python and selenium
but I did not mange to get it.
My code:
test = driver.find_element(By.XPATH, "//*[local-name()='svg' and #class='highcharts-root']//*[local-name()='g' and #class='highcharts-axis-labels highcharts-xaxis-labels']//*[name()='text']").text
print(test)
To extract the texts e.g. Sep-18, Nov-22 you have to induce WebDriverWait for visibility_of_all_elements_located() and you can use either of the following locator strategies:
Using CSS_SELECTOR and text attribute:
print([my_elem.text for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "svg.highcharts-root g.highcharts-axis-labels.highcharts-xaxis-labels text")))])
Using XPATH and get_attribute("innerHTML"):
print([my_elem.get_attribute("innerHTML") for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//*[local-name()='svg' and #class='highcharts-root']//*[local-name()='g' and #class='highcharts-axis-labels highcharts-xaxis-labels']//*[local-name()='text']")))])
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
References
You can find a couple of relevant detailed discussions in:
Reading title tag in svg?
Creating XPATH for svg tag

Selenium find attribute value (Python)

I would like to get all attribute values names 'href' from a website, there are like 10 of them. I have successfully got one using the following method:
url = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "/html/body/div[2]/div[2]/div/div/div[2]/section[1]/div/div[2]/div[3]/ul/li[1]/div/div[1]/span/a"))).get_attribute("href")
The problem with this is it's only giving back one not all of them. I have tried to go by ID but it doesn't return anything:
url = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "a"))).get_attribute("href")
Also, the other href values are located in different xpaths:
/html/body/div[2]/div[2]/div/div/div[2]/section[1]/div/div[2]/div[3]/ul/li[2]/div/div[1]/span/a
/html/body/div[2]/div[2]/div/div/div[2]/section[1]/div/div[2]/div[3]/ul/li[3]/div/div[1]/span/a
/html/body/div[2]/div[2]/div/div/div[2]/section[1]/div/div[2]/div[3]/ul/li[4]/div/div[1]/span/a
Here's my element:
<a ph-tevent="job_click" ref="linkEle" href.bind="getUrl(linkEle, 'job', eachJob, '', eachJob.jobUrl)" data-ph-at-id="job-link" data-ph-id="ph-page-element-page20-CRUCUZ" class="au-target" au-target-id="181" ph-click-ctx="job" ph-tref="12313123213" ph-tag="ph-search-results-v2" href="https://hyperlink.com" data-ph-at-job-title-text="title" data-ph-at-job-location-text="Unknown" data-ph-at-job-location-area-text="asd" data-ph-at-job-category-text="Manufacturing" data-access-list-item="2" data-ph-at-job-id-text="A123124" data-ph-at-job-type-text="Regular" data-ph-at-job-industry-text="Manufacturing" data-ph-at-job-post-date-text="2021-12-09T00:00:00.000Z" data-ph-at-job-seqno-text="ASD212ASFS" aria-label="Senior Manager">
<div class="job-title" data-ph-id="ph-page-element-page20-0Mi3Ce">
<!--anchor-->
<!--anchor-->
<span data-ph-id="ph-page-element-page20-PLxqta">Senior Manager </span>
</div><!--anchor--> </a>
Any help is appreciated!
For finding more than one web element, you should either use find_elements or if you are using Explicit waits then you can use presence_of_all_elements_located or visibility_of_all_elements_located.
Based on the HTML that you've shared, if
this css
a[ph-tevent='job_click'][ref='linkEle']
or this xpath
//a[#ph-tevent='job_click' and #ref='linkEle']
represent all the nodes, to check below are the steps:
Please check in the dev tools (Google chrome) if we have all desired nodes entry in HTML DOM or not.
Steps to check:
Press F12 in Chrome -> go to element section -> do a CTRL + F -> then paste the xpath and see, if your desired elements are getting highlighted or not.
If they are then the below code should work:
for ele in driver.find_elements(By.XPATH, "//a[#ph-tevent='job_click' and #ref='linkEle']"):
print(ele.get_attribute('href'))
To extract the value of the href attributes using Selenium and python you have to induce WebDriverWait for visibility_of_all_elements_located() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
print([my_elem.get_attribute("href") for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "a[ph-tevent='job_click'][ref='linkEle'][data-ph-at-id='job-link'][ph-click-ctx='job'][href]")))])
Using XPATH:
print([my_elem.get_attribute("href") for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//a[#ph-tevent='job_click' and #ref='linkEle'][#data-ph-at-id='job-link' and #ph-click-ctx='job'][#href]")))])
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

How to scrape data from an anchor tag, which is inside another anchor tag in selenium python

I am scraping data from a dynamic site using python and selenium web driver.
How to scrape the href of an element, which is inside nested anchor tags?
<h3 class="">
Ultimate Content Writing
</h3>
This site has lots of links with h3 anchor tags of the above kind, which are all to be scraped. I captured all those anchor tags using the code,
links = driver.find_elements_by_tag_name("h3")
then I did,
for link in links:
href = driver.find_element_by_link_text(link.text).get_attribute('href')
which contains unwanted actions and slows down my program.
How to fetch the href of each link in more efficient way?
The href attributes are not within the <h3> tags but within the <a> tags. So instead of find_elements_by_tag_name("h3") you can use either of the following Locator Strategies:
Using css_selector:
print(driver.find_elements_by_css_selector("h3>a").get_attribute("href"))
Using xpath:
print(driver.find_elements_by_xpath("//h3/a").get_attribute("href"))
Using CSS_SELECTOR and get_attribute("innerHTML"):
print([my_elem.get_attribute("href") for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "h3>a")))])
Using XPATH and text attribute:
print([my_elem.get_attribute("href") for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//h3/a")))])
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

Categories

Resources