我正在使用 selenium 和 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 循环后才会发生,该循环试图找到下一个按钮并进入较大的按钮。(如果我没有正确理解这一点,请告诉我,因为我对这些东西比较陌生。)
此外,我每次运行程序后输出的数据都是不同的(考虑到错误,这是有道理的,因为过去,StaleElementReferenceExceptions 发生在零星的位置。如果每次发生此异常时它都会重复结果,那么对于重复也会偶尔发生。更糟糕的是,每次我运行程序时都会跳过不同批次的结果 - 我交叉比较了来自 2 个不同输出的结果,并且有一些结果出现在一个而不是其他。
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 的方式有其他建议,以便改进我未来的编程,我将不胜感激。
非常感谢!