1

I am wanting to click all the Href tabs under the main headers and to navigate to those pages to scrape them. For speed of the job, I do am wanting to click the href without having to click the headers. My question is, is there a way to click these buttons even though it is not visible like the page on the right? It does not seem to be working for me. It seems to give me:

Traceback (most recent call last):
  File "C:/Users/Bain3/PycharmProjects/untitled4/Centrebet2.py", line 58, in <module>
    EC.element_to_be_clickable((By.XPATH, '(//*[@id="accordionMenu1_ulSports"]/li/ul/li/ul/li/a)[%s]' % str(index + 1)))).click()
  File "C:\Users\Bain3\Anaconda3\lib\site-packages\selenium\webdriver\support\wait.py", line 80, in until
    raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message: 

I have replaced

EC.element_to_be_clickable((By.XPATH, '(//*[@id="accordionMenu1_ulSports"]/li/ul/li/ul/li/a)[%s]' % str(index + 1)))).click()

with

driver.find_element_by_xpath('(//*[@id="accordionMenu1_ulSports"]/li/ul/li/ul/li/a)[%s]' % str(index + 1)).click()

This however does not seem to remedy it as it only clicks visible elements.

My code below is:

from random import shuffle
from selenium.webdriver.support.ui import WebDriverWait as wait

from selenium import webdriver as web
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import TimeoutException
from random import randint
from time import sleep
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import csv
import requests
import time
from selenium import webdriver

success = False
while not success:
    try:
        driver = webdriver.Chrome()
        driver.set_window_size(1024, 600)
        driver.maximize_window()
        driver.get('http://centrebet.com/')
        success = True
    except:
        driver.quit()

sleep(5)

sports = driver.find_element_by_id("accordionMenu1_ulSports")
if sports.get_attribute("style") == "display: none;":
    driver.find_element_by_xpath('//ul[@id="menu_acc"]/li[3]/a').click()

driver.find_element_by_xpath(".//*[@data-type ='sports_l1'][contains(text(), 'Soccer')]").click()

driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

options = driver.find_elements_by_xpath('//*[@id="accordionMenu1_ulSports"]/li/ul/li/ul/li/a')

# Get list of inetegers [1, 2, ... n]
indexes = [index for index in range(len(options))]
# Shuffle them
shuffle(indexes)
for index in indexes:
    # Click on random option
    wait(driver, 10).until(
        EC.element_to_be_clickable((By.XPATH, '(//*[@id="accordionMenu1_ulSports"]/li/ul/li/ul/li/a)[%s]' % str(index + 1)))).click()

enter image description here

I have also tried:

driver.execute_script('document.getElementByxpath("//*[@id="accordionMenu1_ulSports"]/li/ul/li/ul/li/a").style.visibility = "visible";') 

To remedy this. Though this simply gives an error. Any ideas on how to resolve this issue of invisible elements?

NarendraR
  • 7,577
  • 10
  • 44
  • 82
Tetora
  • 433
  • 8
  • 25

2 Answers2

1

You can even try using JavascriptExecutor.

Use below code to make your style attribute = display:block;

driver.execute_script("arguments[0].style.display = 'none'", driver.find_element_by_xpath("//*[@id='accordionMenu1_ulSports']/li/ul/li/ul"))

Note : Make sure you are using correct xpath. your <ul> element is hidden not <a> so so take xpath of that <ul> tag only and try

NarendraR
  • 7,577
  • 10
  • 44
  • 82
  • It still seems to give me an error and is not clicking – Tetora Sep 09 '17 at 13:07
  • The last line driver.find_element_by_xpath('(//*[@id="accordionMenu1_ulSports"]/li/ul/li/ul/li/a)[%s]' % str(index + 1)).click() as it seems to only want to click visible elements (Element not visible error). #driver.execute_script("arguments[0].style.display = 'none'", driver.find_element_by_xpath("//ul[@id='accordionMenu1_ulSports']/li/ul/li/ul[%s]' % str(index + 1)")) also did not work for me as it was unable to locate – Tetora Sep 10 '17 at 05:37
1
driver.execute_script('document.getElementByxpath("//*[@id="accordionMenu1_ulSports"]/li/ul/li/ul/li/a").style.visibility = "visible";')

gives you error because it's not correct way to use XPath in Javascript. Correct way you can find here

To scrape required data you can use below code:

import requests
import time
from selenium import webdriver

url = "http://centrebet.com/"
success = False
while not success:
try:
    driver = webdriver.Chrome()
    driver.set_window_size(1024, 600)
    driver.maximize_window()
    driver.get(url)
    success = True
except:
    driver.quit()

time.sleep(5)

sports = driver.find_element_by_id("accordionMenu1_ulSports")
links = [url + link.get_attribute("onclick").replace("menulink('", "").replace("')", "") for link in sports.find_elements_by_xpath('.//a[starts-with(@onclick, "menulink")]')]
for link in links:
    print(requests.get(link).text)

Instead of clicking on each link, you can request content of each page with HTTP-GET

Andersson
  • 51,635
  • 17
  • 77
  • 129
  • 1
    I have tried something like: function (getElementByXpath("//ul[@id='accordionMenu1_ulSports']/li/ul/li/ul[%s]' % str(index + 1)")))) { return document.evaluate("//ul[@id='accordionMenu1_ulSports']/li/ul/li/ul[%s]' % str(index + 1)")), document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; } console.log(getElementByXpath("//ul[@id='accordionMenu1_ulSports']/li/ul/li/ul[%s]' % str(index + 1)"))")); But python does not like it. I have also tried use HTTP though it appears to stop after Href. http://textuploader.com/d68g3 scraped data https://ibb.co/kZmNYa – Tetora Sep 10 '17 at 06:12
  • Did you try my code exactly as it appears in my answer? – Andersson Sep 10 '17 at 06:24
  • Yes. It tended to scrape a lot of stuff that I am not wanting to scrape. Is there a way to click invisible elements I can't seem to get it working. – Tetora Sep 10 '17 at 06:27
  • It just returns you the content of each tab. You can then get required data from this content. You can replace `print(requests.get(link).text)` with `driver.get(link)` and use common approach to get data – Andersson Sep 10 '17 at 06:35
  • Oh I thought you were only able to navigate with Href clearly displayed. It seems to work okay though it navigates to all the href rather than just Soccer specific. links = [url + link.get_attribute("onclick").replace("menulink('", "").replace("')", "") for link in sports.find_elements_by_xpath('.//*[@id="accordionMenu1_ulSports"]/li/ul/li/ul/li/a')] does not seem to work. Hmm – Tetora Sep 10 '17 at 06:53
  • So you want to get data only for links within Soccer tab, right? – Andersson Sep 10 '17 at 06:59
  • use `soccer = driver.find_element_by_xpath(//a[.="Soccer"]/following-sibling::ul)` instead of `sports = driver.find_element_by_id("accordionMenu1_ulSports")` – Andersson Sep 10 '17 at 07:12
  • Hmm its giving incorrect css for sports = driver.find_element_by_xpath("//a[.='Soccer']/following-sibli‌​ng::ul"). I think the following tag is incorrect. – Tetora Sep 10 '17 at 07:18
  • 1
    //a[.='Soccer']//following-sibling::ul seemed to work. This is an awesome method I can use. Is there a way to click invisible elements with Selenium though I think that would have a lot of uses. – Tetora Sep 10 '17 at 07:21
  • `selenium` should provide you with user-like behavior: if user cannot do something (like clicking on hidden links) - `selenium` also won't do – Andersson Sep 10 '17 at 17:06