Как нажать на кнопку с текстом "Найти округ, в котором я нахожусь, через Селен и Питон в Jupyter"

Вот HTML-код кнопки, которую я хочу нажать на нее: я думаю, что я должен схватить видимую (я думаю)

 <form id="search-form">
                  <div class="input-group hidden-xs">
                    <span class="input-group-btn">
                      <button class="btn btn-default" type="button" onclick="getUserExactLocation();scrollToMap();">Find What County I'm In</button>
                    </span>
                    <input type="text" class="form-control" placeholder="Enter address here" id="address">
                    <span class="input-group-btn">
                      <button class="btn btn-default" type="button" onclick="findAddress();scrollToMap();">Find County for Address</button>
                    </span>
                  </div>
                  <div class="input-group visible-xs">
                    <input type="text" class="form-control" placeholder="Enter address here" id="address-xs">
                    <button class="btn btn-default xs-btn" type="button" onclick="findAddress();scrollToMap();">Find County for Address</button>
                    <button class="btn btn-default xs-btn" type="button" onclick="getUserExactLocation();scrollToMap();">Find What County I'm In</button>
                  </div>
                </form>

Я могу поместить данные в область поиска. Тем не менее, я не могу отправить свою кнопку, чтобы получить данные возврата: у меня есть этот код ниже:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup as bs
from requests_futures.sessions import FuturesSession
from urllib.parse import urljoin
from collections import namedtuple

driver=webdriver.Chrome()
driver.get("https://www.mapdevelopers.com/what-county-am-i-in.php")
mainsoup = bs(driver.page_source, 'lxml') 

listB=[]
listC= ['1209 SE 2nd Ave,Grand Rapids,MN,55744', '415 9th Avenue,Granite Falls,MN,56241', '22 East 6th St,Mantorville,MN,55955']

for query in listC:
    address= driver.find_element_by_id("address")
    address.send_keys(query)
    submitButton=driver.find_element_by_css_selector("button[onclick*='getUserExactLocation();scrollToMap();']").click()
    county_result= driver.find_element_by_id('display_county')
    listB = listB + [county_result.text]
print(listB)

Для submitButton я также стараюсь:

submitButton= driver.find_element_by_css_selector('button.btnbtn-defaultxs-btn').click()

а также

driver.find_element_by_xpath("//button[@class='btn btn-default xs-btn'][@type='button'][contains(., 'input-group visible-xs')]").click()

Результат должен выглядеть так:

["Yellow Medicine County", "Yellow Medicine County", "Dodge County"]

3 ответа

Решение

Кажется, ты был довольно близко. Вам нужно вызвать WebDriverwait перед вводом местоположений в поле " Введите адрес здесь", и вы можете использовать следующее решение:

  • Блок кода:

    from selenium import webdriver
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    
    options = webdriver.ChromeOptions()
    options.add_argument("start-maximized")
    options.add_argument("disable-infobars")
    options.add_argument("--disable-extensions") 
    driver = webdriver.Chrome(chrome_options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
    driver.get("https://www.mapdevelopers.com/what-county-am-i-in.php")
    listB = []
    listC = ['1209 SE 2nd Ave,Grand Rapids,MN,55744', '415 9th Avenue,Granite Falls,MN,56241', '22 East 6th St,Mantorville,MN,55955']
    for query in listC:
        address = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input.form-control#address")))
        address.clear()
        address.send_keys(query)
        driver.find_element_by_xpath("//button[@class='btn btn-default' and starts-with(@onclick, 'getUserExactLocation')]").click()
        # In the next line instead of the element with text as "County" you need to handle the "::before" / "::after" Pseudo Element
        county_result = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//div[@class='row county-result']")))
        listB.append(county_result.text)
    print(listB)
    
  • Консольный вывод:

    ['County', 'County', 'County']
    

Вместо этого вы можете сделать более эффективный запрос xhr post и проанализировать ответ json.

import requests 
url = 'https://www.mapdevelopers.com/data.php?operation=geocode'
headers = {
  'User-Agent': 'Mozilla/5.0',
  'Accept': 'application/json, text/javascript, */*; q=0.01'}

listB=[]
listC= ['1209 SE 2nd Ave,Grand Rapids,MN,55744', '415 9th Avenue,Granite Falls,MN,56241'] #, '22 East 6th St,Mantorville,MN,55955']

for query in listC:
    body = {'address' : query}
    res = requests.post(url, data = body).json()
    listB.append(res['data']['county'])
print(listB)

С помощью запроса HTTP GET. Я полагаю, что запрос на геокодирование теперь ожидает еще 2 обязательных параметра «крышка» и «lcode» (не уверен, что это такое), они перехватываются путем анализа ответа при загрузке страницы, еще один HTTP-запрос на получение gecocode API будет содержать все необходимые параметры. , дает ожидаемые данные json.

      import urllib.request
import urllib.parse
import json

url = "https://www.mapdevelopers.com/what-is-my-address.php"
resource = urllib.request.urlopen(url)
contents = resource.read().decode('utf-8')
lid = contents.split("var lid = \"")[1].split("\"")[0]
lcode = contents.split("var lcode = \"")[1].split("\"")[0]
# pass address here
address = urllib.parse.quote_plus("New Delhi")
print("Getting location details for - ", address)
url = "https://www.mapdevelopers.com/data.php?operation=geocode&address="+address+"&lcode="+lcode+"&lid="+lid
resource = urllib.request.urlopen(url)
JSON_object = json.loads(resource.read().decode('utf-8'))
print(JSON_object)
Другие вопросы по тегам