Python / Selenium "hover-and-click" не работает на WebElement, класс которого изменяется при наведении - PullRequest
0 голосов
/ 14 мая 2018

Я использую библиотеку Selenium на Python для очистки сайта, написанного на js. Моя стратегия состоит в том, чтобы перемещаться по сайту с использованием селена и в нужное время очищать его с помощью BeautifulSoup. Это отлично работает на простых тестах, за исключением случаев, когда, как показано на следующем рисунке, Мне нужно нажать на кнопку «<». </a>

«Класс» кнопки изменяется при наведении, поэтому я использую ActionChains, чтобы перейти к элементу и щелкнуть по нему (я также использую режим сна, чтобы дать браузеру достаточно времени для загрузки страницы). Python не выдает никаких исключений, но щелчок не работает (т. Е. Календарь не перемещается назад).

Ниже я привожу упомянутый веб-сайт и код, который я написал, с примером. У вас есть идея, почему это происходит и / или как я могу преодолеть эту проблему? Большое спасибо.

Сайт = https://burocomercial.profeco.gob.mx/index.jsp

Код:

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time

driver = webdriver.Chrome(path_to_webdriver)
driver.get('https://burocomercial.profeco.gob.mx/index.jsp') #access website

# Search bar and search button
search_bar = driver.find_elements_by_xpath('//*[@id="txtbuscar"]')
search_button = driver.find_element_by_xpath('//*[@id="contenido"]/div[2]/div[2]/div[2]/div/div[2]/div/button')

# Perform search
search_bar[0].send_keys("inmobiliaria")
search_button.click()

# Select result
time.sleep(2)
xpath='//*[@id="resultados"]/div[4]/table/tbody/tr[1]/td[5]/button'
driver.find_elements_by_xpath(xpath)[0].click()

# Open calendar    
time.sleep(5)
driver.find_element_by_xpath('//*[@id="calI"]').click() #opens calendar
time.sleep(2)

# Hover-and-click on "<" (Here's the problem!!!)
cal_button=driver.find_element_by_xpath('//div[@id="ui-datepicker-div"]/div/a') 
time.sleep(4)
ActionChains(driver).move_to_element(cal_button).perform() #hover
prev_button = driver.find_element_by_class_name('ui-datepicker-prev') #catch element whose class was changed by the hover
ActionChains(driver).click(prev_button).perform() #click
time.sleep(1)
print('clicked on it a second ago. No exception was raised, but the click was not performed')
time.sleep(1) 

Ответы [ 2 ]

0 голосов
/ 14 мая 2018

Это другой подход с использованием запросов.Я думаю, что Selenium должен быть последним вариантом для использования при создании веб-страниц.Обычно можно получить данные с веб-страницы, эмулирующей запросы, сделанные веб-приложением

import requests
from bs4 import BeautifulSoup as BS
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36'}
## Starts session
s = requests.Session()
s.headers = headers
url_base = 'https://burocomercial.profeco.gob.mx/'
ind = 'index.jsp'
resp0 = s.get(url_base+ind) ## First request, to get the 'name' parameter that is dynamic
soup0 = BS(resp0.text, 'lxml')
param_name = soup0.select_one('input[id="txtbuscar"]')['name']
action = 'BusGeneral' ### The action when submit the form
keyword = 'inmobiliaria' # Word to search
data_buscar = {param_name:keyword,'yy':'2017'} ### Data submitted
resp1 = s.post(url_base+action,data=data_buscar) ## second request: make the search
resp2 = s.get(url_base+ind) # Third request: retrieve the results
print(resp2.text)
queja = 'Detalle_Queja.jsp' ## Action when Quejas selected
data_queja = {'Lookup':'2','Val':'1','Bus':'2','FI':'28-Nov-2016','FF':'28-Feb-2017','UA':'0'} # Data for queja form
## Lookup is the number of the row in the table, FI is the initial date and FF, the final date, UA is Unidad Administrativa
## You can change these parameters to obtain different queries.
resp3 = s.post(url_base+queja,data=data_queja) # retrieve Quejas results
print(resp3.text)

С этим я получил:

'\r\n\r\n\r\n\r\n\r\n\r\n1|<h2>ABITARE PROMOTORA E INMOBILIARIA, SA DE CV</h2>|0|0|0|0.00|0.00|0|0.00|0.00|0.00|0.00|0 % |0 % ||2'

Который содержит данные, которые используютсяна веб-странице.Возможно, этот ответ не совсем то, что вы ищете, но я думаю, вам будет проще использовать запросы.

0 голосов
/ 14 мая 2018

Вам не нужно парить <, просто щелкните по нему. </p>

from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome(path_to_webdriver)
driver.get('https://burocomercial.profeco.gob.mx/index.jsp') #access website

# set up wait
wait = WebDriverWait(driver, 10)

# Perform search
driver.find_element_by_id('txtbuscar').send_keys("inmobiliaria")
driver.find_element_by_css_selector('button[alt="buscar"]').click()

# Select result
xpath='//*[@id="resultados"]/div[4]/table/tbody/tr[1]/td[5]/button'
wait.until(EC.element_to_be_clickable((By.XPATH, xpath))).click()

# Open calendar    
wait.until(EC.element_to_be_clickable((By.ID, 'calI'))).click() #opens calendar
wait.until(EC.element_to_be_visible((By.ID, 'ui-datepicker-div'))

# Click on "<"
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'a[title="Ant"]'))).click()

Несколько вещей

  1. Если ваш XPath состоит только из идентификатора, просто используйте .find_element_by_id(). Это быстрее и проще для чтения.

  2. Если вы используете только первый элемент в коллекции, например, search_bar, просто используйте .find_element_* вместо .find_elements_* и search_bar[0].

  3. Не используйте сны. Сон - плохая практика и приводит к ненадежным испытаниям. Вместо этого используйте ожидаемые условия, например подождать, пока элемент кликабелен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...