Уведомления

Группа в Telegram: присоединиться

#1 Фев. 14, 2019 12:16:58

Room_on
Зарегистрирован: 2019-02-14
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Мультипоточность и мультипроцессинг при парсинге сайтов

Всем добрый день. Пишу парсер сайта, который должен обходить 60 тыс. страниц с карточками товара и собирать с них нужные атрибуты. Использую список из 16 тыс. прокси и 1 тыс. юзер-агентов, из которых выбираю сочетание случайным образом. Если ответа нет в течение 5 секунд, то беру следующий прокси. В среднем 1 из 5 раз удается получить страницу. Основное время, как я понимаю, уходит на ожидание ответа страницы. Результаты пишу в CSV.

Вопрос 1.
Сейчас делаю всё в 100 потоков через мультипроцессинг. Занимает около 4 Гб оперативной памяти.
Имеет ли смысл использовать мультипоточность? Или может быть стоит сделать мультипоточность внутри мультипроцессинга? Есть ли разница?

Вопрос 2.
При записи в CSV часть строк получаются кривые, попадает только часть фразы из поля. Такое впечатление, что процессы конфликтуют между собой при записи в один и тот же файл. Может ли действительно быть такое и как это исправить?

Вопрос 3.
Как сделать так, чтобы разные процессы обменивались между собой переменными? Например, сделать единый счетчик кол-во обработанных страниц, т.е. чтобы разные процессы увеличивали переменную на +1. Сейчас получается, что в каждом процессе своя переменная (делаю через Global).

Вопрос 4.
Как правильно писать результаты в БД? Если делать в лоб, то могу после парсинга каждой страницы открывать соединение, запускать нужный курсор, делать комит и закрывать соединение. Но наверное это не очень оптимально. Можно ли открыть одно соединение на все процессы/потоки и писать результаты в одну таблицу?

Заранее спасибо за ответы и советы.

Офлайн

#2 Фев. 14, 2019 14:02:56

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 1412
Репутация: +  201  -
Профиль   Отправить e-mail  

Мультипоточность и мультипроцессинг при парсинге сайтов

Room_on
Сейчас делаю всё в 100 потоков через мультипроцессинг. Занимает около 4 Гб оперативной памяти.
Имеет ли смысл использовать мультипоточность? Или может быть стоит сделать мультипоточность внутри мультипроцессинга? Есть ли разница?
это тема для целого холовара… в каждом конкретном случае будет свой ответ. можете почитать https://stackoverflow.com/questions/3044580/multiprocessing-vs-threading-python и решить что в вашем случае подходит больше.
Room_on
Вопрос 2.
При записи в CSV часть строк получаются кривые, попадает только часть фразы из поля. Такое впечатление, что процессы конфликтуют между собой при записи в один и тот же файл. Может ли действительно быть такое и ка
шо серьезно? у вас все 100 процессов одновеременно пишут в один файл? данунах.
НО не думаю что у вас кривые строки именно изза этого(хотя конечно все может быть). Честно говоря я сомневаюсь что вы можете одновременно открыть файл на запись из нескольких процессов.
Но все же:
1 существуют блокираторы(Lock) для подобных случаев.
2. если у вас 100 процессов, ИМХО лучше завести отдельный процесс который будет брать данные из очереди(Queue в самом простом случае) и писать данные в файл, а остальные процессы будут вместо записи в файл кидать данные в очередь.
Room_on
Как сделать так, чтобы разные процессы обменивались между собой переменными?
гуглите Value Array и Manager
https://docs.python.org/3.4/library/multiprocessing.html#sharing-state-between-processes

Room_on
Вопрос 4.
Как правильно писать результаты в БД? Если делать в лоб, то могу после парсинга каждой страницы открывать соединение, запускать нужный курсор, делать комит и закрывать соединение. Но наверное это не очень оптимально. Можно ли открыть одно соединение на все процессы/потоки и писать результаты в одну таблицу?
ровно так же как и в вопросе 2, создаете отдельный процесс, котроый берет данные из очереди и пишет в БД, остальные процессы эти данные помешают в очередь.

Отредактировано PEHDOM (Фев. 14, 2019 14:09:09)

Офлайн

#3 Фев. 14, 2019 14:55:17

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2131
Репутация: +  148  -
Профиль   Отправить e-mail  

Мультипоточность и мультипроцессинг при парсинге сайтов

> Сейчас делаю всё в 100 потоков через мультипроцессинг….Имеет ли смысл использовать мультипоточность? Или может быть стоит сделать мультипоточность внутри мультипроцессинга?

Какая ОС? С какой целью multiprocessing используется?



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Онлайн

#4 Фев. 14, 2019 14:59:14

JOHN_16
От: Россия, Петропавловск-Камчатск
Зарегистрирован: 2010-03-22
Сообщения: 3280
Репутация: +  220  -
Профиль   Отправить e-mail  

Мультипоточность и мультипроцессинг при парсинге сайтов

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



_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Офлайн

#5 Фев. 14, 2019 17:08:49

Room_on
Зарегистрирован: 2019-02-14
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Мультипоточность и мультипроцессинг при парсинге сайтов

Rodegast
> Какая ОС? С какой целью multiprocessing используется?

Запускаю локально на компе, Win10. Multiprocessing использую с целью ускорения прохода по всем страницам, т.к. в каждом потоке одна страница в среднем секунд 20 загружается (1 из 5 прокси срабатывает только).

Офлайн

#6 Фев. 14, 2019 17:10:46

Room_on
Зарегистрирован: 2019-02-14
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Мультипоточность и мультипроцессинг при парсинге сайтов

JOHN_16
в современном мире все больше такие задачи решаются асинхронным программированием.Писать все в 1 файл это конечно безумие.
Стал писать для каждого процесса в свой файл (типа SpawnPoolWorker-1.csv), кривых строк стало гораздо меньше, но всё равно иногда встречаются.

Офлайн

#7 Фев. 14, 2019 17:40:23

JOHN_16
От: Россия, Петропавловск-Камчатск
Зарегистрирован: 2010-03-22
Сообщения: 3280
Репутация: +  220  -
Профиль   Отправить e-mail  

Мультипоточность и мультипроцессинг при парсинге сайтов

ну самое просто сейчас, не пишите в файл. Соберите все данные в памяти, и только потом пишите в файл. “кривых” совсем не будет. У вас же проблема с конкурентным доступом.



_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Офлайн

#8 Фев. 14, 2019 20:26:58

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2131
Репутация: +  148  -
Профиль   Отправить e-mail  

Мультипоточность и мультипроцессинг при парсинге сайтов

> Multiprocessing использую с целью ускорения прохода по всем страницам

Твоя основная ошибка в том что ты пытаешься решить конкурентную задачу при помощи многопоточности (да ещё и самым хреновым способом, хотя он единственный в случае Python-а). Для конкурентности используй модуль threading или асинхронность, тогда вопросы 2 и 3 сам собой отпадут.

> 1 из 5 прокси срабатывает только

Что мешает заранее удалить не работающие прокси?

> Можно ли открыть одно соединение на все процессы/потоки и писать результаты в одну таблицу?

Да, так и нужно делать.

> Такое впечатление, что процессы конфликтуют между собой при записи в один и тот же файл. …. Стал писать для каждого процесса в свой файл (типа SpawnPoolWorker-1.csv), кривых строк стало гораздо меньше, но всё равно иногда встречаются.

Вызывай перед закрытием файла:

 file.flush()
os.fsync(file)



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Отредактировано Rodegast (Фев. 14, 2019 20:39:29)

Онлайн

#9 Фев. 14, 2019 21:01:17

Room_on
Зарегистрирован: 2019-02-14
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Мультипоточность и мультипроцессинг при парсинге сайтов

JOHN_16
ну самое просто сейчас, не пишите в файл. Соберите все данные в памяти, и только потом пишите в файл. “кривых” совсем не будет. У вас же проблема с конкурентным доступом.

Rodegast
Твоя основная ошибка в том что ты пытаешься решить конкурентную задачу при помощи многопоточности (да ещё и самым хреновым способом, хотя он единственный в случае Python-а). Для конкурентности используй модуль threading или асинхронность, тогда вопросы 2 и 3 сам собой отпадут.
Первый вопрос был про быстродействие. Увеличивает ли её многопроцессорность по сравнению с многопоточностью. В моём понимании многопоточность позволяет хорошо ускорить задачи, в которых есть простой по времени, как в моём случае. То есть задача ждет ответа сервера до 5 секунд, потом берет следующий прокси. Пока одна задача ждет, то другой поток может запустить другую задачу и т.д. Но запустить 60 тыс. ссылок на страницы в 60 тыс. потоков наверное не самый правильный подход. И как я понял многопотоность ограничивается ресурсами одного ядра процессора. Многопроцессорность позволяет в свою очередь использовать все ресурсы. В связи с этим мне кажется, что нужно сделать несколько процессов, а в каждом из них несколько потоков. Правильно ли я понимаю логику?

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

Rodegast
Вызывай перед закрытием файла:

Пишу в файл следующим образом, где proc - имя процесса
 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)

Офлайн

#10 Фев. 14, 2019 22:00:15

Room_on
Зарегистрирован: 2019-02-14
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Мультипоточность и мультипроцессинг при парсинге сайтов

JOHN_16
ну самое просто сейчас, не пишите в файл. Соберите все данные в памяти, и только потом пишите в файл. “кривых” совсем не будет. У вас же проблема с конкурентным доступом.
Подумал и понял, что пока не понимаю, как в памяти собрать данные из разных процессов. Сейчас если делаю глобальную переменную-счётчик кол-ва спарсенных страниц, то в каждом процессе свой подсчёт идёт, а не глобальный.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version