Как я могу выполнить итерацию по списку python и остановиться, чтобы загрузить следующий URL-адрес, прежде чем продолжить процесс?

#python #list #selenium #loops #web-scraping

#питон #Список #селен #петли #очистка веб-страниц

Вопрос:

Я научился выполнять (используя python) создание нескольких разных веб-скребков с целью очистки URL-адресов изображений с одного из веб-сайтов нашего производителя деталей для массовой загрузки таблицы загрузки продуктов, причем один из столбцов состоит из URL-адресов изображений.

Поскольку URL-адреса не являются простыми (я не могу просто перебирать список номеров продуктов и добавлять его к каждому новому URL-адресу или любым из более простых методов; Я здесь, потому что я должен быть здесь), и поскольку на сайте нет функции «поиск по номеру продукта», я пошелк спискам на их сайте. У них были действительно удобные инструменты! Вы можете добавлять продукты по номеру продукта, и когда вы закончите, вы можете экспортировать этот список как a .csv с возможностью включения ссылок на все соответствующие страницы продукта. И это было здорово, пока я не создал свой скрипт и не обнаружил, что у них есть ограничение в 250 элементов на список. Для перспективы мне нужно очистить чуть менее 5000 продуктов (это означает, что мне понадобится около 20 списков, из которых 19 заполнены, а последний почти заполнен).

Я упоминаю все это, поскольку контекст для него имеет отношение к рассматриваемому коду и проблеме.

Теперь, когда у меня действительно нет других вариантов, моя цель — взять мой код и немного изменить его, чтобы выполнить очистку через 20 отдельных списков. Прямо сейчас, на соответствующем этапе, он получает URL-адрес, который переходит по ссылке на их веб-сайт для списка, который я назвал testlist , и затем обновляет страницу, чтобы убедиться, что все элементы в порядке.

Мы были на нужной странице, когда мне нужен был один список, но есть одна проблема: мы больше не можем использовать только одну ссылку, так как нам нужно будет что-то настроить, чтобы перебирать 250 элементов и создавать новый список около 20 раз (или я могу вручную создавать списки и иметь определенные URL-адресачтобы указать на).

Наша вторая проблема — это само ограничение элемента. Мой цикл for — это один большой цикл, предназначенный для перебора всего списка из примерно 4800 номеров продуктов, которые у меня есть, добавляя их один за другим в список на той же странице. Нам нужно разбить это на куски по 250 элементов на страницу, не более, и загрузить другой URL-адрес списка. Я мог бы создать эти списки вручную, чтобы у меня были конкретные URL-адреса для указания, но, если будет проще добавить функцию, которая просто нажимает и называет ее, это было бы здорово. Вероятно, я могу разобраться с этой частью сам.

Я не знаю, куда идти дальше. У меня есть код, созданный для обработки одного списка веб-сайтов по одному URL-адресу, перебирающий номера продуктов в моем списке python, а затем экспортирующий его в конце.

Мне нужно, чтобы мой скрипт выполнял итерацию по тому же списку python, останавливаясь после 250 номеров продуктов, чтобы загрузить следующий URL-адрес, прежде чем продолжить процесс.

Часть моего кода, которая получает наш URL-адрес списка, а затем переходит в скребковую часть, выглядит следующим образом.

 
# get the url for our list
listurl = 'https://www.thewebsiteimscraping.com/products/list-manager?listid=3925' # <- this is the URL for one particular list; other lists will have different list IDs
alert_accept()
driver.get(listurl)
alert_accept()

############################################################################################

driver.refresh()
# import our list, the Select function, the By function for selections, expected conditions, and our time function so we can sleep 
from kiberlist import mfrnumbers
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
import time
# from testnumber import testnumbers as tlnum 


for number in mfrnumbers:
    
        # we find the listactions menu, and utilize the "add item" option
        WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#listActions")))
        alert_accept()
        print('Finding listactions...')
        select_am = Select(driver.find_element_by_css_selector('#listActions'))
        alert_accept()
        print("Found it. Selecting...")
        select_am.select_by_value('addItems')
        print('Selected. Next...')
        
        # paste our item number into the box paste it 
        print('Locating model number search....')
        inputidbox = driver.find_element_by_id('model-number-search')
        print('Located? Pasting model number...')
        inputidbox.send_keys(number)  
        
        # finally add our item
        additembutton = driver.find_element_by_css_selector('.gtmAddItemToList')
        print('Located add item button...')
        additembutton.click()   
        print('Item number added. Next...')
        print('Locating blank space...')
        WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#addItemsToListModal > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > button:nth-child(1) > svg:nth-child(1) > path:nth-child(1)")))
        time.sleep(1)
        xbutton = driver.find_element_by_css_selector('#addItemsToListModal > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > button:nth-child(1) > svg:nth-child(1) > path:nth-child(1)')
        xbutton.click()
        time.sleep(1)

 
        
# now we find the "export excel" option to get our csv for that list  
listactions = Select(driver.find_element_by_css_selector('#listActions'))
listactions.select_by_value('exportExcel')

# clicky clicky. user dialog will show up on screen asking if you want to save the file. user must manually click on save 
exportbutton = driver.find_element_by_css_selector('#btnExportToExcel')
exportbutton.click()

 

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

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

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

1. Вы вложили много усилий в этот вопрос, но название все портит! я бы предложил обновить это, чтобы ваш вопрос мог привлечь больше внимания.

2. Привет! Я отредактировал пух, чтобы пользователи могли помочь вам с вашей проблемой, не отвлекаясь.

3. @Ironkey спасибо! Я знаю, что это был не очень четкий вопрос, но я на самом деле не был уверен, что туда поместить..

4. Нет проблем! Надеюсь, вы получите необходимую помощь 🙂

5. @haise0 С удовольствием!

Ответ №1:

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

Обычно вы видите «преобразовать список списков в один плоский список». Это как раз наоборот.

Я предполагаю, что mfrnumbers — это ваш единый список. Мы создадим функцию-генератор, которая, учитывая один flattened_list, возвращает элементы list_id и в этом списке. Как указано в вашем вопросе, вы поймете, как на самом деле получить этот список. Так что на данный момент я предполагаю list_id , что это простое целое число.

Эта функция get_list(mfrnumbers) вернет эти числа в группах max_items_per_list . Технически, он возвращает итератор, который вы будете повторять.

 def get_list(flattened_list, max_items_per_list=250):
    # maybe you have some pattern for list names?
    list_id = 1

    while len(flattened_list) > 0:
        current_list = flattened_list[:max_items_per_list]
        yield list_id, current_list

        flattened_list = flattened_list[len(current_list):]
        list_id  = 1
 

И мы можем вызвать эту функцию следующим образом:

 for (myid, mylist) in get_list([1,2,3,4,5], max_items_per_list=2):
    print (myid, mylist)
 

Выходной сигнал:

 1 [1, 2]
2 [3, 4]
3 [5]
 

Таким образом, в вашем случае вы бы запустили весь свой большой цикл for number in mfrnumbers как внутренний цикл, но с выводом get_list .

 for (myid, mylist) in get_list(mfrnumbers):
    # stop and do any loading for this new list...
    for number in mylist:
       .....