私はセレンと BeautifulSoup を使用して、Web サイト ( 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 つの異なる出力からの結果を相互比較したところ、1 つの出力ではなく 1 つの出力に存在する結果がいくつかありました。他の。
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 を使用した方法について他に推奨事項がある場合は、それをいただければ幸いです。
本当にありがとう!