Как сделать мой веб-скрипт более надежным? - PullRequest
0 голосов
/ 11 июня 2019

Я запустил код для удаления веб-сайта Сантандера.

Царапины, кажется, работают, за исключением того, что я получаю ложные результаты. И когда я запускаю код дважды подряд, результаты меняются.

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

def hw_santander_scrap(Amount, Duration):
  from selenium import webdriver
  from selenium.webdriver.support.ui import WebDriverWait
  from selenium.webdriver.support import expected_conditions as EC
  chrome_options = webdriver.ChromeOptions()
  chrome_options.add_argument('--headless')
  chrome_options.add_argument('--no-sandbox')
  chrome_options.add_argument('--disable-dev-shm-usage')
  chrome_options.add_argument('--start-maximized')
  chrome_options.add_argument('window-size=10000x5000')
  webdriver = webdriver.Chrome('chromedriver', chrome_options = chrome_options)

  #
  import time
  maintenant = DT.now()
  period = str(maintenant.day) + '_' + str(maintenant.month) + '_' + str(maintenant.year)
  print('Start Scraping')

  ################################################ Santander###############################################

  Santander = pd.DataFrame({
      'Project': "reforma vivienda",
      'Period': period,
      'Monthly repayment': [0],
      'TIN': [0],
      'TAE': [0],
      'Total repayment': [0],
      'Initial amount': [0],
      'Duration': [0]
  })

  project = pd.DataFrame({
      'Project': "reforma vivienda",
      'Period': period,
      'Monthly repayment': [0],
      'TIN': [0],
      'TAE': [0],
      'Total repayment': [0],
      'Initial amount': [0],
      'Duration': [0]
  })
  url = 'https://simuladores.bancosantander.es/SantanderES/loansimulatorweb.aspx?por=webpublica&prv=publico&m=300&cta=1&ls=0#/t0'
  webdriver.get(url)

  Max_amount = 90.000
  Min_amount = 3.000
  for i in range(len(Amount)):
    Simulated_amount = Amount[i]
    if Simulated_amount > Max_amount:
      pass
    elif Simulated_amount < Min_amount:
      pass
    else :
      amount = WebDriverWait(webdriver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "#amount")))
      amount.clear()
      amount.send_keys("{:.3f}".format(Simulated_amount))
      WebDriverWait(webdriver, 30).until(lambda webdriver: webdriver.execute_script('return jQuery.active') == 0)
      for j in range(len(Duration)):
        Simulated_duration = Duration[j]
        Simulated_duration = round(int(Simulated_duration))
        Max_duration = 96
        Min_duration = 12
        if Simulated_duration > Max_duration:
          pass
        elif Simulated_duration < Min_duration:
          pass
        else :
          term = WebDriverWait(webdriver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "#term")))
        term.clear()
        term.send_keys("{}".format(Simulated_duration))
        term.send_keys(Keys.TAB)
        webdriver.save_screenshot('screenshot_santander.png')
        project.loc[j, 'Project'] = "reforma vivienda"
        project.loc[j, 'Initial amount'] = float("{:.3f}".format(Amount[i]).replace('.', ''))
        project.loc[j, 'Duration'] = Simulated_duration
        project.loc[j, 'Period'] = str(maintenant.day) + '/' + str(maintenant.month) + '/' + str(maintenant.year)
        project.loc[j, 'Monthly repayment'] = webdriver.find_element_by_css_selector('.r1 span').text.replace(' €', '').replace(',', '.')
        project.loc[j, 'TIN'] = float(webdriver.find_element_by_css_selector('.r3 span').text[6: 10].replace(',', '.'))
        project.loc[j, 'TAE'] = float(webdriver.find_element_by_css_selector('.r3 span').text[13: 17].replace(',', '.'))
        project.loc[j, 'Total repayment'] = float(webdriver.find_element_by_css_selector('.r7 span').text.replace(' €', '').replace('.', '').replace(',', '.'))
      Santander = Santander.append(project)
  Santander = Santander.loc[Santander.TIN != 0,: ]
  Santander.to_csv('Santander_{}.csv'.format(period), index = False)
print('End Scraping')

Для запуска кода:

Amount = [13.000, 14.000, 15.000, 30.000, 45.000, 60.000]
Duration = [12, 15, 24, 36, 48, 60, 72, 84, 96]
hw_santander_scrap(Amount, Duration)

Ответы [ 2 ]

2 голосов
/ 12 июня 2019

Эти данные взяты из XHR.Поэтому просто используйте запросы, чтобы опубликовать свои значения и проанализируйте ответ с помощью json.loads

. Используйте вкладку сети браузера, чтобы увидеть, как выглядит запрос.

1 голос
/ 11 июня 2019

Это мое время сиять!

Информация:

В настоящее время я работаю над агрегатором финансовых данных, который столкнулся с точно такой же проблемой.

Он собираетданные примерно с дюжины веб-сайтов и организуют их в объект JSON, который затем используется сайтом Flask для отображения данных.

Эти данные извлекаются с веб-сайтов, имеющих несколько подкаталогов с похожим содержимым, которые имеют разныйселекторы.

Как вы можете себе представить, с фреймворком, подобным selenium, это становится очень сложным, поэтому единственное решение состоит в том, чтобы его опустить.

Решение:

Простота - это ключ , поэтому я удалил все зависимости, кроме библиотеки BeautifulSoup и requests.

Затем я создал три класса и функцию для каждого filter [1]

from bs4 import BeautifulSoup

class GET:
  def text(soup, selector, index = 0):
    selected = soup.select(selector)
    if len(selected) > index:
      return selected[index].text.strip()

class Parse:
  def common(soup, selector):
    return GET.text(soup, selector, index = 5)

class Routes:
  def main(self):
    data = {}
    if self.is_dir_1:
      data["name"] = GET.text(self.soup, "div")
      data["title-data"] = Parse.common(self.soup, "p > div:nth-child(1)")
    elif self.is_dir_2:
      data["name"] = GET.text(self.soup, "p", index = 2)
      data["title-data"] = Parse.common(self.soup, "p > div:nth-child(5)")
    return data

def filter_name(url: str, response: str, filter_type: str):
  if hasattr(Routes, filter_type):
    return getattr(Routes, filter_type)(to_object({
      "is_dir_1": bool("/sub_dir_1/" in url),
      "is_dir_2": bool("/sub_dir_1/" in url),
      "soup": BeautifulSoup(html, "lxml")
    }))
  return {}

Используя библиотеку requests, я сделал запрос на получение данных, затем передал URL, текст ответа и тип_фильтра в функцию filter_name.

Затем в функции filter_namen Я использовал аргумент filter_type, чтобы передать «суп» в целевую функцию маршрута и выбрать каждый элемент и получить там его данные.

Затем в функции целевого маршрута я использовалусловие if для определения подкаталога и присвоения текста объекту данных.

После того, как все это завершено, я возвратил объект data.

Этот метод очень прост исохранил мой код СУХОЙ, он даже позволяет использовать необязательные пары key: value.

Вот код для вспомогательного класса to_object:

class to_object(object):
  def __init__(self, dictionary):
    self.__dict__ = dictionary

Это преобразует словари в объекты, поэтому вместо этогонеобходимости всегда писать:

self["soup"]

Вы бы написали:

self.soup

Исправление ошибок:

Вам действительно нужно стандартизировать тип отступа, который вы используете, потому что вашСценарий вызывает следующую ошибку:

Traceback (most recent call last):
  File "", line 84
    Amount =   [13.000, 14.000, 15.000, 30.000, 45.000, 60.000]
    ^
IndentationError: unindent does not match any outer indentation level

Примечания: * Фильтры

  1. - это сценарии, которые очищают разные сайты, мой проект требует, чтобы я очистил несколько сайтов, чтобы получить необходимые данные.
  2. попробуй привести тебя в порядокБолее того, аккуратный код легче читать и проще писать

Надеюсь, это поможет, удачи.

...