Форум сайта python.su
Всем добрый день. Пишу парсер сайта, который должен обходить 60 тыс. страниц с карточками товара и собирать с них нужные атрибуты. Использую список из 16 тыс. прокси и 1 тыс. юзер-агентов, из которых выбираю сочетание случайным образом. Если ответа нет в течение 5 секунд, то беру следующий прокси. В среднем 1 из 5 раз удается получить страницу. Основное время, как я понимаю, уходит на ожидание ответа страницы. Результаты пишу в CSV.
Вопрос 1.
Сейчас делаю всё в 100 потоков через мультипроцессинг. Занимает около 4 Гб оперативной памяти.
Имеет ли смысл использовать мультипоточность? Или может быть стоит сделать мультипоточность внутри мультипроцессинга? Есть ли разница?
Вопрос 2.
При записи в CSV часть строк получаются кривые, попадает только часть фразы из поля. Такое впечатление, что процессы конфликтуют между собой при записи в один и тот же файл. Может ли действительно быть такое и как это исправить?
Вопрос 3.
Как сделать так, чтобы разные процессы обменивались между собой переменными? Например, сделать единый счетчик кол-во обработанных страниц, т.е. чтобы разные процессы увеличивали переменную на +1. Сейчас получается, что в каждом процессе своя переменная (делаю через Global).
Вопрос 4.
Как правильно писать результаты в БД? Если делать в лоб, то могу после парсинга каждой страницы открывать соединение, запускать нужный курсор, делать комит и закрывать соединение. Но наверное это не очень оптимально. Можно ли открыть одно соединение на все процессы/потоки и писать результаты в одну таблицу?
Заранее спасибо за ответы и советы.
Офлайн
Room_onэто тема для целого холовара… в каждом конкретном случае будет свой ответ. можете почитать https://stackoverflow.com/questions/3044580/multiprocessing-vs-threading-python и решить что в вашем случае подходит больше.
Сейчас делаю всё в 100 потоков через мультипроцессинг. Занимает около 4 Гб оперативной памяти.
Имеет ли смысл использовать мультипоточность? Или может быть стоит сделать мультипоточность внутри мультипроцессинга? Есть ли разница?
Room_onшо серьезно? у вас все 100 процессов одновеременно пишут в один файл? данунах.
Вопрос 2.
При записи в CSV часть строк получаются кривые, попадает только часть фразы из поля. Такое впечатление, что процессы конфликтуют между собой при записи в один и тот же файл. Может ли действительно быть такое и ка
Room_onгуглите Value Array и Manager
Как сделать так, чтобы разные процессы обменивались между собой переменными?
Room_onровно так же как и в вопросе 2, создаете отдельный процесс, котроый берет данные из очереди и пишет в БД, остальные процессы эти данные помешают в очередь.
Вопрос 4.
Как правильно писать результаты в БД? Если делать в лоб, то могу после парсинга каждой страницы открывать соединение, запускать нужный курсор, делать комит и закрывать соединение. Но наверное это не очень оптимально. Можно ли открыть одно соединение на все процессы/потоки и писать результаты в одну таблицу?
[code python][/code]
Отредактировано PEHDOM (Фев. 14, 2019 14:09:09)
Офлайн
> Сейчас делаю всё в 100 потоков через мультипроцессинг….Имеет ли смысл использовать мультипоточность? Или может быть стоит сделать мультипоточность внутри мультипроцессинга?
Какая ОС? С какой целью multiprocessing используется?
Офлайн
в современном мире все больше такие задачи решаются асинхронным программированием.
Писать все в 1 файл это конечно безумие.
Офлайн
Rodegast
> Какая ОС? С какой целью multiprocessing используется?
Офлайн
JOHN_16Стал писать для каждого процесса в свой файл (типа SpawnPoolWorker-1.csv), кривых строк стало гораздо меньше, но всё равно иногда встречаются.
в современном мире все больше такие задачи решаются асинхронным программированием.Писать все в 1 файл это конечно безумие.
Офлайн
ну самое просто сейчас, не пишите в файл. Соберите все данные в памяти, и только потом пишите в файл. “кривых” совсем не будет. У вас же проблема с конкурентным доступом.
Офлайн
> Multiprocessing использую с целью ускорения прохода по всем страницам
Твоя основная ошибка в том что ты пытаешься решить конкурентную задачу при помощи многопоточности (да ещё и самым хреновым способом, хотя он единственный в случае Python-а). Для конкурентности используй модуль threading или асинхронность, тогда вопросы 2 и 3 сам собой отпадут.
> 1 из 5 прокси срабатывает только
Что мешает заранее удалить не работающие прокси?
> Можно ли открыть одно соединение на все процессы/потоки и писать результаты в одну таблицу?
Да, так и нужно делать.
> Такое впечатление, что процессы конфликтуют между собой при записи в один и тот же файл. …. Стал писать для каждого процесса в свой файл (типа SpawnPoolWorker-1.csv), кривых строк стало гораздо меньше, но всё равно иногда встречаются.
Вызывай перед закрытием файла:
file.flush() os.fsync(file)
Отредактировано Rodegast (Фев. 14, 2019 20:39:29)
Офлайн
JOHN_16
ну самое просто сейчас, не пишите в файл. Соберите все данные в памяти, и только потом пишите в файл. “кривых” совсем не будет. У вас же проблема с конкурентным доступом.
RodegastПервый вопрос был про быстродействие. Увеличивает ли её многопроцессорность по сравнению с многопоточностью. В моём понимании многопоточность позволяет хорошо ускорить задачи, в которых есть простой по времени, как в моём случае. То есть задача ждет ответа сервера до 5 секунд, потом берет следующий прокси. Пока одна задача ждет, то другой поток может запустить другую задачу и т.д. Но запустить 60 тыс. ссылок на страницы в 60 тыс. потоков наверное не самый правильный подход. И как я понял многопотоность ограничивается ресурсами одного ядра процессора. Многопроцессорность позволяет в свою очередь использовать все ресурсы. В связи с этим мне кажется, что нужно сделать несколько процессов, а в каждом из них несколько потоков. Правильно ли я понимаю логику?
Твоя основная ошибка в том что ты пытаешься решить конкурентную задачу при помощи многопоточности (да ещё и самым хреновым способом, хотя он единственный в случае Python-а). Для конкурентности используй модуль threading или асинхронность, тогда вопросы 2 и 3 сам собой отпадут.
RodegastА одни и те же прокси, то срабатывают, то нет + иногда капчу на них выдает, которая со временем проходит. Поэтому поставил таймаут 5 секунд на ожидание ответа.
Что мешает заранее удалить не работающие прокси?
Rodegast
Вызывай перед закрытием файла:
def write_csv(data, proc): with open('result ' + proc + '.csv', 'a+', encoding='utf-8', newline='') as f: writer = csv.writer(f, quotechar = "'", delimiter=',') writer.writerow((data['name'], data['id'] data['price'], data['url'], data['proxy'], data['proc']))
Отредактировано Room_on (Фев. 14, 2019 21:03:40)
Офлайн
JOHN_16Подумал и понял, что пока не понимаю, как в памяти собрать данные из разных процессов. Сейчас если делаю глобальную переменную-счётчик кол-ва спарсенных страниц, то в каждом процессе свой подсчёт идёт, а не глобальный.
ну самое просто сейчас, не пишите в файл. Соберите все данные в памяти, и только потом пишите в файл. “кривых” совсем не будет. У вас же проблема с конкурентным доступом.
Офлайн