Я получаю желаемые результаты, но думаю, что код можно улучшить. В настоящее время он довольно медленный и подвержен ошибкам при очистке нескольких страниц подряд. Код ниже очищает 5 функций для 42 транспортных средств (21 на страницу). Я собираю в общей сложности 18 функций (остальные 13 функций здесь не показаны) для этих двух страниц, но это занимает слишком много времени, учитывая, что я sh обработаю в общей сложности 29 страниц.
Чтобы увидеть цену автомобиля, вам необходимо войти в систему, поэтому я использую Selenium, как показано в коде ниже.
import pandas as pd
import requests
from bs4 import BeautifulSoup
import re
import numpy as np
from selenium import webdriver
import time
from IPython.core.interactiveshell import InteractiveShell #optional
# Change cell settings (optional)
InteractiveShell.ast_node_interactivity = "all"
pd.options.display.max_rows = 100
pd.options.display.max_colwidth = 100
pd.options.display.max_columns = None
driver = webdriver.Chrome()
#driver.maximize_window() #optional
# Log in and search
urls = ["https://www.example.com/"]
for url in urls:
driver.get(url)
time.sleep(1)
driver.find_elements_by_class_name("dropdown-toggle")[0].click()
time.sleep(1)
driver.find_elements_by_name('email')[0].send_keys("arjenvgeffen@hotmail.com")
time.sleep(1)
driver.find_elements_by_name("submit")[0].click()
time.sleep(2)
link = driver.find_element_by_link_text('SEARCH')
time.sleep(1)
link.click()
time.sleep(2)
driver.find_elements_by_name("searchScope")[0].send_keys('ALL PAST')
time.sleep(1)
driver.find_elements_by_name("searchMake")[0].send_keys('PLYMOUTH')
time.sleep(1)
driver.find_elements_by_name('searchModel')[0].send_keys('Cuda')
time.sleep(1)
driver.find_elements_by_name('searchYearStart')[0].send_keys("1970")
time.sleep(1)
driver.find_elements_by_name('searchYearEnd')[0].send_keys("1971")
time.sleep(1)
driver.find_element_by_xpath("//button[. = 'Search']").click()
time.sleep(1)
Приведенный ниже код очищает название транспортного средства (year_make_model_type), цену (которую вы можете увидеть только после входа в систему выше по электронной почте) и URL страницы. На следующем этапе page_urls будет использоваться для сбора информации по каждой странице продукта. Это занимает слишком много времени при очистке 29 страниц, и это может пропустить / застрять. Любое улучшение здесь высоко ценится!
# Scrape two pages (these two variables can be scraped without being on the vehicle page)
i = 0
x = 1
year_make_model_type = []
price = []
while True:
for i in range(0,1):
time.sleep(2)
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
time.sleep(2)
urls = [x.get('href') for x in soup.findAll("a", class_ = "lot-title")]
time.sleep(2)
mystring = 'https://www.example.com'
page_urls = [mystring + s for s in urls]
time.sleep(2)
for y in soup.find_all("a", class_ = ("lot-title")):
year_make_model_type.append(y.text)
time.sleep(2)
for p in soup.find_all("span", class_ = ("lot-price")):
price.append(re.sub("[\$\,]", "", p.text))
time.sleep(2)
i +=1
for x in range(2,3):
time.sleep(5)
driver.find_element_by_xpath('//a[@href="/search/page/%d/"]' % (x,)).click()
time.sleep(5)
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
time.sleep(2)
page_products_urls = [x.get('href') for x in soup.findAll("a", class_ = "lot-title")]
time.sleep(2)
mystring = 'https://www.example.com'
page_products_urls2 = [mystring + s for s in page_products_urls]
page_urls.extend(page_products_urls2)
time.sleep(2)
for y in soup.find_all("a", class_ = ("lot-title")):
year_make_model_type.append(y.text)
time.sleep(2)
for p in soup.find_all("span", class_ = ("lot-price")):
price.append(re.sub("[\$\,]", "", p.text))
time.sleep(2)
x += 1
if x == 2:
break
else:
break
len(page_urls) #42
len(set(page_urls)) #42
len(price) #42
len(set(price)) #36
len(year_make_model_type) #42
len(set(year_make_model_type)) #13
# If you need to go back to the first page
#driver.find_element_by_xpath('//a[@href="/search/page/1/"]').click()
# Create df
scraped_data = pd.DataFrame({'url': page_urls, 'year_make_model_type': year_make_model_type, 'price':price})
scraped_data['price'] = scraped_data['price'].replace('', np.NaN)
scraped_data['price'] = scraped_data['price'].astype(float)
scraped_data.shape
scraped_data.head()
#driver.quit()
Этот последний фрагмент кода счищает основные моменты и флаг_группы для каждого транспортного средства со страницы его продукта.
# Create additional features per product url (have to click on product to be able to scrape these features)
def getAndParseURL(url):
result = requests.get(url)
soup = BeautifulSoup(result.text, 'html.parser')
return(soup)
highlights = []
flag_group = []
# Add features per vehicle
for url in page_urls:
# Vehicle highlights
highlights1 = []
soup = getAndParseURL(url)
if not soup.find("ul", class_ = "lot-highlights hidden-print"):
highlights1.append(np.NaN)
else:
hl = soup.find("ul", class_ = "lot-highlights hidden-print").text.strip()
hl = hl.replace("\n", ", ").strip()
highlights1.append(hl)
highlights.extend(highlights1)
# Vehicle flag_group
attraction = []
soup = getAndParseURL(url)
flag = soup.find(class_=["flag flag-main","flag flag-star", "flag flag-feature"])
if flag:
attraction.append(flag.contents[0])
else:
attraction.append(np.NaN)
flag_group.extend(attraction)
# Assign new features to existing df
scraped_data = scraped_data.assign(**{'highlights': highlights, 'flag_group': flag_group})#, 'reserve': reserve})
scraped_data.shape
scraped_data.head()
Дайте мне знать / покажите мне, где, по вашему мнению, код выше можно улучшить. Спасибо, что нашли время!