Форум программистов, компьютерный форум, киберфорум
Python: Web
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
0 / 0 / 0
Регистрация: 14.04.2014
Сообщений: 6

Многопроцессорный парсер теряет ссылки при паринге (selenium+PhantomJS+ProcessPoolExecutor)

19.08.2016, 10:31. Показов 2286. Ответов 9

Студворк — интернет-сервис помощи студентам
Я хочу написать парер для некоторого вебсайта,
который имеет много JS кодов. Для этого я решил выб-
рать связку Selenium+PhantomJS+lxml. Работаю на Python
Парсер необходим достаточно быстрый, что бы обраба-
тывал не менее 1000 ссылок за 1 час. Для этой цели
я решил использовать многопроцессорность. (не ммного-
поточночность - из-за GIL!). Для разбиения на процессы
использовал concurrent.Future.ProcessPoolExecutor.

Проблема в следующем, я например, даю на вход 10
ссылок, на выходе обрабатываетя в лучшем случае 9
(может и 6). Это плохо! Есть еще некоторая зависимость
с увеличением количества потоков увеличивается количество
утеряных ссылок. Первое что я решил сделать, это
проследить где идет обрыв программы, где она перестает
выполняться. (assert в моем случае на сколько я понял
не пойдет, из за многопроцессорности). Тут я определил
что обрыв идет в функции browser.get(l) - не загружает
страницу. Я попробовал добавить time.sleep(x), потом
добавил wait видимый и не видимый. Тоже ничего не из-
менилось. Начал исследовать функцию get() c модуля
selenium, нашел что она перезагружать с того же модуля
функцию execute(), и там я залез в дебри, что мои
знания не позволяют разобраться, да и времени особо нет.
И в то же время, я попробвал запустить в один процесс.
То есть количество процессов = 1. И тоже одна ссылка
потерялась. Это навело на мысль, что возможно дело не
в selenium+phantomJS, а в ProcessPoolExecutor. Я заменил
этот модуль на multiproessing.Pool - и о чудо, ссылки
перестали теряться. Но вместо этого появилась другая
проблема, более 4 потоков не выполняет. Если ставишь
больше, выдает следующую ошибку:
"""
multiprocessing.pool.RemoteTraceback:
Traceback (most recent call last):
File "/usr/lib/python3.4/multiprocessing/pool.py", line 119, in worker
result = (True, func(*args, **kwds))
File "/usr/lib/python3.4/multiprocessing/pool.py", line 44, in mapstar
return list(map(*args))
File "interface.py", line 34, in hotline_to_mysql
w = Parse_hotline().browser_manipulation(lin k)
File "/home/water/work/parsing/class_parser/parsing_classes.py", line 352, in browser_manipulation
browser.get(l)
File "/usr/local/lib/python3.4/dist-packages/selenium/webdriver/remote/webdriver.py", line 247, in get
self.execute(Command.GET, {'url': url})
File "/usr/local/lib/python3.4/dist-packages/selenium/webdriver/remote/webdriver.py", line 233, in execute
response = self.command_executor.execute(driver_com mand, params)
File "/usr/local/lib/python3.4/dist-packages/selenium/webdriver/remote/remote_connection.py", line 401, in execute
return self._request(command_info[0], url, body=data)
File "/usr/local/lib/python3.4/dist-packages/selenium/webdriver/remote/remote_connection.py", line 471, in _request
resp = opener.open(request, timeout=self._timeout)
File "/usr/lib/python3.4/urllib/request.py", line 463, in open
response = self._open(req, data)
File "/usr/lib/python3.4/urllib/request.py", line 481, in _open
'_open', req)
File "/usr/lib/python3.4/urllib/request.py", line 441, in _call_chain
result = func(*args)
File "/usr/lib/python3.4/urllib/request.py", line 1210, in http_open
return self.do_open(http.client.HTTPConnection, req)
File "/usr/lib/python3.4/urllib/request.py", line 1185, in do_open
r = h.getresponse()
File "/usr/lib/python3.4/http/client.py", line 1171, in getresponse
response.begin()
File "/usr/lib/python3.4/http/client.py", line 351, in begin
version, status, reason = self._read_status()
File "/usr/lib/python3.4/http/client.py", line 321, in _read_status
raise BadStatusLine(line)
http.client.BadStatusLine: ''

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "interface.py", line 69, in <module>
main()
File "interface.py", line 63, in main
executor.map(hotline_to_mysql, link_list)
File "/usr/lib/python3.4/multiprocessing/pool.py", line 260, in map
return self._map_async(func, iterable, mapstar, chunksize).get()
File "/usr/lib/python3.4/multiprocessing/pool.py", line 599, in get
raise self._value
http.client.BadStatusLine: ''
"""
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  import random
    import time
    import lxml.html as lh
    from selenium import webdriver
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
    from multiprocessing import Pool
    from selenium.webdriver.common.keys import Keys
    from concurrent.futures import Future, ProcessPoolExecutor, ThreadPoolExecutor
    AMOUNT_PROCESS = 5
 
    def parse(h)->list:
        # h - str, html of page
        lxml_ = lh.document_fromstring(h)
        name = lxml_.xpath('/html/body/div[2]/div[7]/div[6]/ul/li[1]/a/@title')
        prices_ = (price.text_content().strip().replace('\xa0', ' ')
                    for price in lxml_.xpath('//*[@id="gotoshop-price"]'))
        markets_ =(market.text_content().strip() for market in
                lxml_.find_class('cell shop-title'))
        wares = [[name[0], market, price] for (market, price)
                in zip(markets_, prices_)]
        return wares
 
 
    def browser_manipulation(l):
        #options =  []
        #options.append('--load-images=false')
        #options.append('--proxy={}:{}'.format(host, port))
        #options.append('--proxy-type=http')
        #options.append('--user-agent={}'.format(user_agent)) #тут хедеры рандомно
 
        dcap = dict(DesiredCapabilities.PHANTOMJS)
        #user agent takes from my config.py
        dcap["phantomjs.page.settings.userAgent"] = (random.choice(USER_AGENT))
        browser = webdriver.PhantomJS(desired_capabilities=dcap)
        #print(browser)
        #print('~~~~~~', l)
        #browser.implicitly_wait(20)
        #browser.set_page_load_timeout(80)
        #time.sleep(2)
        browser.get(l)
        time.sleep(20)
        result = parse(browser.page_source)
        #print('++++++', result[0][0])
        browser.quit()
        return result
 
    def main():
        #open some file with links
 
        with open(sys.argv[1], 'r') as f:
            link_list = [i.replace('\n', '') for i in f]
        with Pool(AMOUNT_PROCESS) as executor:
            executor.map(browser_manipulation, link_list)
 
    if __name__ == '__main__':
        main()
Собственно вопросы: где может быть ошибка? из-за
селениума и фантома, ProcessPoolExecutora, или я где
то код написал не правильно?
Как можно увеличить скорость парсинга что бы 1000
ссылок, за 1 час. ?
Наконец, может есть какой то другой способ паринга
динамических страниц? (само собой на питоне)
Спасибо за ответы.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
19.08.2016, 10:31
Ответы с готовыми решениями:

Парсер с использованием Selenium, phantomJS
Доброго времени суток. Подскажите, пожалуйста по следующему вопросу: есть сайт (https://www.sofascore.com/ru), я хочу получить с него...

Selenium+PhantomJS
Не могу понять в чем проблема. Парсю страничку kingtaro.com Проблема со временем, если я использую FireFox вебдрайвер, то все гуд. А если...

PhantomJS + Selenium
Как можно скрыть эту консоль которая запускается вместе с winForms? нашел такой код, но чета он не работает. Как открывалась консоль, так и...

9
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
19.08.2016, 13:38
Qwebkit можно использовать и там потоки или процессы не нужны будут, потому что этот модуль асинхронно работает.
0
 Аватар для ilnurgi
141 / 141 / 38
Регистрация: 20.02.2012
Сообщений: 597
19.08.2016, 14:40
я писал такие парсеры на втором питоне используя гринлеты.

зеленые потоки * процессы.

1000 страниц на 4 процесса, по 250 страниц на процесс. с этим я думаю и 10 зеленых потоков справятся.

главное одинаковых сущностей не плодить.

вот у вас на каждом потоке новый браузер. а зачем, нельзя одним обойтись?
0
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
19.08.2016, 14:55
ilnurgi, сопрограммы же не подойдут в случае работы с selenium, этот способ хорошо при работе с requests или чем-то подобным.
1
 Аватар для ilnurgi
141 / 141 / 38
Регистрация: 20.02.2012
Сообщений: 597
19.08.2016, 15:40
alex925, наверное ты прав, да.
надо на практике глянуть
0
0 / 0 / 0
Регистрация: 14.04.2014
Сообщений: 6
19.08.2016, 17:50  [ТС]
alex925, Установил PyQt4 - попробал спарсить одну страничку, не быстрее селениума, если не дольше...

ilnurgi, поищу в ваших темах) но если не трудно, могли бы вы ссылочку бросить ?
0
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
19.08.2016, 17:59
vetal_mart, его идея идеальна для парсинга сайтов без js, а тебе он не подходит.

Добавлено через 5 минут
Вообще если хочешь почитать о сопрограммах, то читай о asyncio и aiohttp. У меня есть парсер основанный на сопрограммах, 50 страничек скачиваются и парсятся за 50 секунд.
0
0 / 0 / 0
Регистрация: 14.04.2014
Сообщений: 6
20.08.2016, 14:51  [ТС]
Благодарю. Посмотрю обязательно и отпишусь)
0
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
20.08.2016, 15:43
P.S опписался, 50 страничек скачиваются и парсятся за 3 сек.
0
0 / 0 / 0
Регистрация: 14.04.2014
Сообщений: 6
23.08.2016, 17:01  [ТС]
попробовал вместо ProcessPoolExecutor - ThreadPoolExecutor, ссылки терять перестал. И в данном случае, работает примерно на той же скорости что и Process.
Впорос еще актуален, если есть мысли по поводу, буду благодарен.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
23.08.2016, 17:01
Помогаю со студенческими работами здесь

Selenium + PhantomJS + прокси
Как подружить вебдрайвер селениума и фантомжс с прокси? # -*- coding: utf8 -*- import os import sys from selenium import...

Selenium + phantomjs + proxy
Возможно ли так сделать? Нагуглить ничего не получилось. Знающие, помогите.

Прокси в Selenium (PhantomJS)
Привет всем, нуждаюсь в помощи касательно того, как задать прокси в Selenium (PhantomJS). Пробовал разные методы, найденные в интернете и...

Selenium phantomjs скачать файл
Добрый день. Подскажите как скачать файл через phantomjs? В сети нашел два примера: public static bool TryDownloadFile(this...

Парсинг js с python, selenium, phantomjs
Здравствуйте! Вот страница https://1xmavemv.com/ru/live/Handball/ (не реклама) Возле каждого матча есть его время, в исходной станице...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
Вывод данных через динамический список в справочнике
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Функция заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
10 пpимет, которые всегда сбываются
Maks 31.03.2026
1. Чтобы, наконец, пришла маршрутка, надо закурить. Если сигарета последняя, маршрутка придет еще до второй затяжки даже вопреки расписанию. 2. Нaдоели зима и снег? Не надо переезжать. Достаточно. . .
Перемещение выделенных строк ТЧ из одного документа в другой
Maks 31.03.2026
Реализация из решения ниже выполнена на примере нетипового документа "ВыдачаОборудованияНаСпецтехнику" с единственной табличной частью "ОборудованиеИКомплектующие" разработанного в конфигурации КА2. . . .
Functional First Web Framework Suave
DevAlt 30.03.2026
Sauve. IO Апнулись до NET10. Из зависимостей один пакет, работает одинаково хорошо как в режиме проекта так и в интерактивном режиме. из сложностей - чисто функциональный подход. Решил. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru