Очистка веб-страниц Selenium с помощью нажатия кнопки «Далее» приводит к дублированию значений - PullRequest
0 голосов
/ 13 февраля 2019

Я использую селен и BeautifulSoup для очистки данных с веб-сайта (http://www.grownjkids.gov/ParentsFamilies/ProviderSearch) с помощью следующей кнопки, которую я нажимаю в цикле. Ранее я боролся с StaleElementReferenceException, но преодолел это путем циклического повторенияэлемент на странице. Однако я столкнулся с новой проблемой - теперь он может щелкнуть до конца. Но когда я проверяю файл csv, в который он записан, хотя большинство данных выглядит хорошо, частоповторяющиеся строки в пакетах по 5 (это число результатов, отображаемых на каждой странице).

Наглядный пример того, что я имею в виду: https://www.dropbox.com/s/ecsew52a25ihym7/Screen%20Shot%202019-02-13%20at%2011.06.41%20AM.png?dl=0

У меня есть догадка, это связано с моимПрограмма повторно извлекает текущие данные на странице каждый раз, когда я пытаюсь найти следующую кнопку. Я был озадачен, почему это произошло, так как, насколько я понимаю, фактическая часть очистки происходит только после того, как вы выйдете из внутреннего цикла while, который пытаетсянайти следующую кнопку и в большую. (Дайте мне знать, если я не понимаю этуточно так же, как я сравнительно новичок в этом деле.)

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

from selenium import webdriver
from selenium.webdriver.chrome.options import Options 
from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException
from bs4 import BeautifulSoup
import csv


chrome_options = Options()  
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument("--headless")  

url = "http://www.grownjkids.gov/ParentsFamilies/ProviderSearch"

driver = webdriver.Chrome('###location###')
driver.implicitly_wait(10)

driver.get(url)

#clears text box 
driver.find_element_by_class_name("form-control").clear()

#clicks on search button without putting in any parameters, getting all the results
search_button = driver.find_element_by_id("searchButton")
search_button.click()

df_list = []
headers = ["Rating", "Distance", "Program Type", "County", "License", "Program Name", "Address", "Phone", "Latitude", "Longitude"]

while True: 
    #keeps on clicking next button to fetch each group of 5 results 
    try:
        nextButton = driver.find_element_by_class_name("next")
        nextButton.send_keys('\n') 
    except NoSuchElementException: 
        break
    except StaleElementReferenceException:
        attempts = 0
        while (attempts < 100):
            try: 
                nextButton = driver.find_element_by_class_name("next")
                if nextButton:
                    nextButton.send_keys('\n') 
                    break
            except NoSuchElementException: 
                break
            except StaleElementReferenceException:
                attempts += 1

    #finds table of center data on the page
    table = driver.find_element_by_id("results")
    html_source = table.get_attribute('innerHTML')
    soup = BeautifulSoup(html_source, "lxml")

    #iterates through centers, extracting the data
    for center in soup.find_all("div", {"class": "col-sm-7 fields"}):
        mini_list = []
        #all fields except latlong
        for row in center.find_all("div", {"class": "field"}):
            material = row.find("div", {"class": "value"})
            if material is not None:
                mini_list.append(material.getText().encode("utf8").strip())
        #parses latlong from link
        for link in center.find_all('a', href = True):
            content = link['href']
            latlong = content[34:-1].split(',')
            mini_list.append(latlong[0])
            mini_list.append(latlong[1])

        df_list.append(mini_list)

#writes content into csv
with open ('output_file.csv', "wb") as f:
    writer = csv.writer(f)
    writer.writerow(headers)
    writer.writerows(row for row in df_list if row)

Всё поможет!Если у вас есть другие рекомендации о том, как я использовал selenium / BeautifulSoup / python, чтобы улучшить свое программирование на будущее, я был бы признателен.

Большое спасибо!

1 Ответ

0 голосов
/ 13 февраля 2019

Я бы использовал селен для подсчета результатов, а затем выполнял бы вызов API для получения реальных результатов.Вы можете либо, в случае, если счетчик результатов превышает предел для pageSize аргумента queryString для API, выполнить цикл в пакетах и ​​увеличивать аргумент currentPage, пока не достигнете общего количества, или, как я делаю ниже, просто запросить всерезультаты за один раз.Затем извлеките то, что вы хотите из json.

import requests
import json
from bs4 import BeautifulSoup as bs
from selenium import webdriver

initUrl = 'http://www.grownjkids.gov/ParentsFamilies/ProviderSearch'
driver = webdriver.Chrome()
driver.get(initUrl)
numResults = driver.find_element_by_css_selector('#totalCount').text
driver.quit()
newURL = 'http://www.grownjkids.gov/Services/GetProviders?latitude=40.2171&longitude=-74.7429&distance=10&county=&toddlers=false&preschool=false&infants=false&rating=&programTypes=&pageSize=' + numResults + '&currentPage=0'
data = requests.get(newURL).json()

У вас есть коллекция словарей для повторения в ответе:

image

Пример написаниянекоторые значения:

if(len(data)) > 0:
    for item in data:
        print(item['Name'], '\n' , item['Address'])

Если вы беспокоитесь о значениях lat и long, вы можете получить их из одного из тегов сценария, когда используете селен:

enter image description here

Альтернативный URL, который я использую для XHR jQuery GET, вы можете найти, используя инструменты dev (F12) на странице, затем обновив страницу с помощью F5 и изучив запросы jquery, сделанные на вкладке сети:

enter image description here

...