Scraping niekompletnych danych z Selenium
Czasami ludzie zbierają oddzielnie różne wartości ze strony
all_names = driver.find_elements_by_xpath('.//h3/a')
all_prices = driver.find_elements_by_class_name('price_color')
all_others = driver.find_elements_by_class_name("other")
a potem grupują ją używając zip()
for row in zip(all_names, all_prices, all_others):
print(row)
ale to może powodować problem jeśli niektóre elementy mają niekompletne dane - jak other
w przykładzie - ponieważ wartości moga zostać przesunięte z jedego elementu do drugiego i mogą stworzyć mniej resultatów niż oczekujemy.
Dla przykładu ten kod nie daje żadnych resultatów ponieważ na stronie nie ma klasy other
więc all_others
jest puste i zip(..., all_others)
nie tworzy żadnych elementów
import selenium.webdriver
driver = selenium.webdriver.Firefox()
driver.get('https://books.toscrape.com')
all_names = driver.find_elements_by_xpath('.//h3/a')
all_prices = driver.find_elements_by_class_name('price_color')
all_others = driver.find_elements_by_class_name('other')
for name, price, other in zip(all_names, all_prices, all_others):
row = [
name.get_attribute('title'),
item.text.strip(),
other.text.strip()
]
print(row)
Lepiej jest znaleźć obiekt, który grupuje wszystkie informacje dla jednego elementu
all_items = driver.find_elements_by_class_name('product_pod')
a potem szukać wartości tylko w tym elemencie używając item
zamiast driver
ponieważ w ten sposób możemy wyłapać, że brakuje wartości i wstawić jakąś wartość domyślną - np. "NAN"
data = []
for item in all_items:
try:
name = item.find_element_by_xpath('.//h3/a').get_attribute('title')
except Exception as ex:
#print('[Exception] name:', ex)
name = 'NAN'
try:
price = item.find_element_by_class_name('price_color').text.strip()
except Exception as ex:
#print('[Exception] price:', ex)
price = 'NAN'
try:
other = item.find_element_by_class_name('other').text.strip()
except Exception as ex:
#print('[Exception] other:', ex)
other = 'NAN'
data.append([name, price, other])
Pełna wersja:
import selenium.webdriver
driver = selenium.webdriver.Firefox()
driver.get('https://books.toscrape.com')
all_items = driver.find_elements_by_class_name('product_pod')
data = []
for item in all_items:
try:
name = item.find_element_by_xpath('.//h3/a').get_attribute('title')
except Exception as ex:
#print('[Exception] name:', ex)
name = ''
try:
price = item.find_element_by_class_name('price_color').text.strip()
except Exception as ex:
#print('[Exception] price:', ex)
price = ''
try:
other = item.find_element_by_class_name('other').text.strip()
except Exception as ex:
#print('[Exception] other:', ex)
other = 'NAN'
data.append([name, price, other])
for row in data:
print(row)
Wynik:
['A Light in the Attic', '£51.77', 'NAN']
['Tipping the Velvet', '£53.74', 'NAN']
['Soumission', '£50.10', 'NAN']
['Sharp Objects', '£47.82', 'NAN']
['Sapiens: A Brief History of Humankind', '£54.23', 'NAN']
['The Requiem Red', '£22.65', 'NAN']
['The Dirty Little Secrets of Getting Your Dream Job', '£33.34', 'NAN']
['The Coming Woman: A Novel Based on the Life of the Infamous Feminist, Victoria Woodhull', '£17.93', 'NAN']
['The Boys in the Boat: Nine Americans and Their Epic Quest for Gold at the 1936 Berlin Olympics', '£22.60', 'NAN']
['The Black Maria', '£52.15', 'NAN']
['Starving Hearts (Triangular Trade Trilogy, #1)', '£13.99', 'NAN']
["Shakespeare's Sonnets", '£20.66', 'NAN']
['Set Me Free', '£17.46', 'NAN']
["Scott Pilgrim's Precious Little Life (Scott Pilgrim #1)", '£52.29', 'NAN']
['Rip it Up and Start Again', '£35.02', 'NAN']
['Our Band Could Be Your Life: Scenes from the American Indie Underground, 1981-1991', '£57.25', 'NAN']
['Olio', '£23.88', 'NAN']
['Mesaerion: The Best Science Fiction Stories 1800-1849', '£37.59', 'NAN']
['Libertarianism for Beginners', '£51.33', 'NAN']
["It's Only the Himalayas", '£45.17', 'NAN']
Użyłem stronu specjalnie do nauki scraping http://books.toscrape.com/ stworzonej przez autorów modułu Scrapy. Warto też zobaczyć inne przykłady danych na stronie http://toscrape.com/.
Buy a Coffee