Как использовать webscraper, работающий на экземпляре EC2 с лямбда-функциями?

#python #amazon-web-services #selenium #aws-lambda

#python #amazon-веб-сервисы #selenium #aws-lambda

Вопрос:

Я создал webscraper, используя python и selenium с помощью geckodriver, в настоящее время он запущен в экземпляре EC2 по расписанию crontab.

Моя проблема в том, что для завершения загрузки требуется более 5 минут, и я хочу использовать функции lamda для запуска моего scraper, но они позволяют выполнять только 5 минут.

Итак, у меня есть код, похожий на этот.

 from selenium import webdriver

def start_browser(url):
    browser = webdriver.Firefox( executable_path="./geckodriver")
    executable_path="./geckodriver")
    browser.get(url)
    return browser

def log_in(user, pass, user_elem, pass_elem, login_elem, browser):
    user_elem.click().send_keys(user)
    pass_elem.click().send_keys(pass)
    login_elem.click()
    return browser

def nav_to_data(browser, data_elem)
    data_elem.click()
    return browser

def find_data(browser, data_table)
    data_links = data_table.find_elements_by_tag_name("tr")
    return data_links, browser

  

Я думаю, что эти функции можно было бы запускать на лямбда-функциях, передавая экземпляры браузера / webdriver друг другу?

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

Есть ли какие-нибудь обходные пути для этого?

 
def download_data(browser, link)
    link.click()
    time.sleep(2)
    download_elem = browser.find_element_by_id("download_xls_file")
    download_path =    download_elem.click()
    return download_path

# THIS TAKES LONGER THAN 5 mins
download_paths = []
for link in data_links:
    download = download_data(browser, link) # clicks a link to a new page wdownload button and returns path to the .xls file
    download_paths.append(download)

upload_data()
  

Комментарии:

1. Лямбда-функции поддерживали ограничение по времени в 15 минут в течение нескольких месяцев, FWIW.

2. вау, я понятия не имел, спасибо!

Ответ №1:

Вы можете разделить свои данные и использовать рекурсивный лямбда-код для обработки фрагментов вашего списка. Беру пример из моего блога

 def invoke_self_async(data_list, context):
    this_data_list = data_list[0:20] # increase number as needed
    new_event = {
        'data': data_list[20:] # needs to match above number
    }
    boto3.client('lambda').invoke_async(
        FunctionName=context.invoked_function_arn,
        InvokeArgs=json.dumps(new_event)
    )
    my_data = []
    for data in data_list:
        download = download_data(browser, data) # returns path  to .xls file
        my_data.append(download)
    return my_data
  

Комментарии:

1. Ах, моя ошибка, что я не сделал это настолько ясным в своем посте, данные в data_list на самом деле являются ссылками для загрузки файлов .xls с моими данными, а не необработанными данными

2. Точно, если загрузка n ссылок занимает у вас более 5 минут, вы можете создать n/x разделы и загрузить каждый из них в своем собственном лямбда-исполнении, invoke_async гарантируя, что ваши лямбды не будут ждать завершения друг друга, поэтому процесс будет отчасти параллельным.

3. ах, я понимаю, что вы имеете в виду, я попробую реализовать это, большое спасибо, это здорово!