Как очистить быстрее, используя Selenium и BeautifulSoup? - PullRequest
0 голосов
/ 14 октября 2019

Благодаря помощи прекрасных людей здесь, на SO, я смог собрать некоторый код для очистки веб-страницы. Из-за динамического характера страницы мне пришлось использовать Selenium, так как BeautifulSoup можно использовать только в одиночку, когда нужно очистить статические страницы.

Один недостаток заключается в том, что весь процесс открытия страницы, ожидания открытия всплывающего окна и ввода информации, занимает огромное количество времени. И здесь проблема времени, так как мне приходится копировать около 1000 страниц (1 страница на почтовый индекс), что занимает около 10 часов.

Как я могу оптимизировать код, чтобы эта операция не заняла так много времени?

Я оставлю полный код и список почтовых индексов ниже для воспроизведения.

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
import time
import pandas as pd

time_of_day=[]
price=[]
Hours=[]
day=[]
disabled=[]
location=[]

danishzip = pd.read_excel (r'D:\Danish_ZIPs.xlsx')

for i in range(len(danishzip)):
    try:
        zipcode = danishzip['Zip'][i]

        driver = webdriver.Chrome(executable_path = r'C:\Users\user\lib\chromedriver_77.0.3865.40.exe')
        wait = WebDriverWait(driver,10)
        driver.maximize_window()
        driver.get("https://www.nemlig.com/")

        wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".timeslot-prompt.initial-animation-done")))
        wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[type='tel'][class^='pro']"))).send_keys(str(zipcode))
        wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".btn.prompt__button"))).click()

        time.sleep(3)
        soup=BeautifulSoup(driver.page_source,'html.parser')


        for morn,d in zip(soup.select_one('[data-automation="beforDinnerRowTmSlt"]').select('.time-block__time'),soup.select_one('[data-automation="beforDinnerRowTmSlt"]').select('.time-block__item')):
            location.append(soup.find('span', class_='zipAndCity').text)
            time_of_day.append(soup.select_one('[data-automation="beforDinnerRowTmSlt"] > .time-block__row-header').text)
            Hours.append(morn.text)
            price.append(morn.find_next(class_="time-block__cost").text)
            day.append(soup.select_one('.date-block.selected [data-automation="dayNmTmSlt"]').text + " " + soup.select_one('.date-block.selected [data-automation="dayDateTmSlt"]').text)
            if 'disabled' in d['class']:
                disabled.append('1')
            else:
                disabled.append('0')

        for after,d in zip(soup.select_one('[data-automation="afternoonRowTmSlt"]').select('.time-block__time'),soup.select_one('[data-automation="afternoonRowTmSlt"]').select('.time-block__item')):
            location.append(soup.find('span', class_='zipAndCity').text)
            time_of_day.append(soup.select_one('[data-automation="afternoonRowTmSlt"] > .time-block__row-header').text)
            Hours.append(after.text)
            price.append(after.find_next(class_="time-block__cost").text)
            day.append(soup.select_one('.date-block.selected [data-automation="dayNmTmSlt"]').text + " " + soup.select_one('.date-block.selected [data-automation="dayDateTmSlt"]').text)
            if 'disabled' in d['class']:
                disabled.append('1')
            else:
                disabled.append('0')

        for evenin,d in zip(soup.select_one('[data-automation="eveningRowTmSlt"]').select('.time-block__time'),soup.select_one('[data-automation="eveningRowTmSlt"]').select('.time-block__item')):
            location.append(soup.find('span', class_='zipAndCity').text)
            time_of_day.append(soup.select_one('[data-automation="eveningRowTmSlt"] > .time-block__row-header').text)
            Hours.append(evenin.text)
            price.append(evenin.find_next(class_="time-block__cost").text)
            day.append(soup.select_one('.date-block.selected [data-automation="dayNmTmSlt"]').text + " " + soup.select_one('.date-block.selected [data-automation="dayDateTmSlt"]').text)
            if 'disabled' in d['class']:
                disabled.append('1')
            else:
                disabled.append('0')

        df = pd.DataFrame({"time_of_day":time_of_day,"Hours":Hours,"price":price,"Day":day,"Disabled" : disabled, "Location": location})
        print(df)
        driver.close()
    except Exception:
        time_of_day.append('No Zipcode')
        location.append('No Zipcode')
        Hours.append('No Zipcode')
        price.append('No Zipcode')
        day.append('No Zipcode')
        disabled.append('No Zipcode')
        df = pd.DataFrame({"time_of_day":time_of_day,"Hours":Hours,"price":price,"Day":day,"Disabled" : disabled, "Location": location})
        driver.close()

Список почтовых индексов: https://en.wikipedia.org/wiki/List_of_postal_codes_in_Denmark

Ответы [ 2 ]

3 голосов
/ 14 октября 2019

Все, что вам нужно, это простой запрос для получения всей информации в формате json:

import requests

headers = {
    'sec-fetch-mode': 'cors',
    'dnt': '1',
    'pragma': 'no-cache',
    'accept-encoding': 'gzip, deflate, br',
    'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/77.0.3865.120 Safari/537.36',
    'accept': 'application/json, text/plain, */*',
    'cache-control': 'no-cache',
    'authority': 'www.nemlig.com',
    'referer': 'https://www.nemlig.com/',
    'sec-fetch-site': 'same-origin',
}

response = requests.get('https://www.nemlig.com/webapi/v2/Delivery/GetDeliveryDays?days=8', headers=headers)

json_data = response.json()

Например, вы можете изменить параметр days= на 20 и получить данные за 20 дней.

1 голос
/ 14 октября 2019

Selenium не предназначен для очистки веб-страниц.

Попробуйте найти внутренний API сайта nemlig.com. Вместо ожидания обработки JS найдите конечные точки http, которые возвращают нужные вам данные. Вы можете сделать это с помощью инструментов разработчика в вашем браузере или некоторых инструментов, таких как Burp Suite.

После этого просто соберите его с помощью запросов / urllib.

https://ianlondon.github.io/blog/web-scraping-discovering-hidden-apis/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...