Форум программистов, компьютерный форум, киберфорум
Python: Web
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.79/34: Рейтинг темы: голосов - 34, средняя оценка - 4.79
4 / 4 / 2
Регистрация: 04.04.2015
Сообщений: 186

Beautiful Soup 4, сравнение html-парсеров при запуске в потоке

04.04.2018, 21:03. Показов 7565. Ответов 47
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте, спарсил страницу с помощью lxml, встроенного в Beautiful Soup - выдал 30 секунд. Не поверил, начал искать ошибки и оптимизировать. Ничего конкретного не получилось, время парсинга примерна такая же. Вспомнил, что у Beautiful Soup есть еще 2 других парсера html.parser и html5lib, в итоге их результаты:
Запуск в отдельном потоке Запуск в общей программе, без создания отдельного потока
html.parser:2 1.44
html5lib: 14 5.5
lxml: 30 1.24

И собственно вопрос, почему в потоке lxml так теряет в скорости? Хотя он считается самым быстрым
Метод запуска потока:
Python
1
2
3
4
5
6
def starting_threading():
    while q.empty()==False:
        if(threading.active_count()<=threads_count):
            t = threading.Thread(target=all_parsing, args=(q,))
            t.start()
            print("Старт потока",t)
q-очередь, threads_count=1.
Вдруг кому-то захочется спарсить эту же страницу ради спортивного интереса: https://www.mvideo.ru/smartfon... rtfony-205 . Парсить только ссылки на телефоны 1 страницы (этой). Пишите библиотеку и язык программирования для сравнения. Должен быть запрос страницы, без сохранения ее на диск, а потом ее парсинга
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
04.04.2018, 21:03
Ответы с готовыми решениями:

Beautiful Soup Python
Я пишу программу открывающую все ссылки на указанной странице и выписывает те, у которых в url есть id= и т.д. Но по какой-то причине в...

Парсинг на Python с Beautiful Soup
Напишите 2 парсера. Первый парсер разработайте для скрапинга сайта pleer.ru, где необходимо вытащить текст из колонки категорий(см. скрин...

Beautiful Soup поиск по атрибуту
Добрый вечер. Подскажите пожалуйста как с помощь bs4 получить все li c data-xxxx, xxxx-каждый раз новое

47
║XLR8║
 Аватар для outoftime
1212 / 909 / 270
Регистрация: 25.07.2009
Сообщений: 4,361
Записей в блоге: 5
13.04.2018, 15:48
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от danilshik Посмотреть сообщение
А возможно ли сохранить результат запроса? Идея такая: сначала получаем результаты запросов, а потом потоками обрабатываем эти страницы? По идее же быстрее должно быть
Быстрее не будет. Не с потоками, не на CPython.

Цитата Сообщение от danilshik Посмотреть сообщение
Уже тестировали, ThreedPool большую выгоду дает
Заблуждаетесь. Вы начинаете асинхронно выкачивать данные, тем самым уменьшая задержки на сетевые операции. Если бы вы делали то что пишете, а именно выкачивали данные синхронно, дабы избежать блокировок и прочего. Время выполнения было бы даже большим чем если бы вы всё делали в одном потоке из-за накладных расходов на управление потоками.

Разберистесь в чем разница между процессом и потоком, и что такое GIL в CPython,
0
4 / 4 / 2
Регистрация: 04.04.2015
Сообщений: 186
13.04.2018, 16:17  [ТС]
Цитата Сообщение от outoftime Посмотреть сообщение
Заблуждаетесь. Вы начинаете асинхронно выкачивать данные, тем самым уменьшая задержки на сетевые операции.
Не совсем понял. Вы хотите отправлять запросы async и все это в пуле?

Добавлено через 2 минуты
Цитата Сообщение от outoftime Посмотреть сообщение
Сообщение от danilshik
Уже тестировали, ThreedPool большую выгоду дает
Про это имелось ввиду: мы отправляем запрос c помощью request, получаем ответ, парсим. Все это в нескольких потоках, процессах. Так вот из всех, ThreedPool на несколько секунд быстрее

Добавлено через 1 минуту
Вот этот код
Код

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
1
 
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
import requests
#from multiprocessing.dummy import Pool as ThreadPool
from multiprocessing import Pool
import logging
from bs4 import BeautifulSoup
import threading
import queue
import lxml.html
log = logging.getLogger(__name__)
count_thread=10
q_list =[]
q_url=queue.Queue()
cities=[]
url_main="https://www.mvideo.ru"
 
 
def parse_list_object(q_list):
    start = time.time()
    url=q_list[0]
    city=q_list[1]
    log.info("Парсинг list: %s | %s",url,city)
    r=requests.get(url)
    html=get_html(r)
    for elem in html.xpath(".//div[@class='c-product-tile sel-product-tile-main ']"):
        error_div=elem.xpath(".//span[@class='c-product-label__text']")
        if(error_div!=[]):
            error_div=error_div[0]
            error_text=error_div.xpath("span[2]/text()")[0]
            if(error_text!="Витринный образец"):
                continue
        link_object=url_main+elem.xpath(".//h4[@class='e-h4 u-pb-0']/a")[0].get("href")+"/shopdirections?cityId="+city
        q_url.put(link_object)
        log.info(link_object)
    end = time.time()
    log.info("Спарсен за %s", end-start)
def parse_object(url):
    r=requests.get(url)
    log.info("Запрос")
    html=get_html(r)
    log.info("Парсинг")
    print("Парсинг")
def start_threads():
    # with ThreadPoolExecutor(count_thread) as executor:
    #     for _ in executor.map(parse_list_object, q_list):
    #         pass
 
    with Pool(count_thread) as p:
        p.map(parse_list_object, q_list)
 
    # pool = ThreadPool(count_thread)
    # results = pool.map(parse_list_object, q_list)
    # pool.close()
    # pool.join()
 
 
def get_html(request):
    return lxml.html.fromstring(request.text)
def parse_city():
    r = requests.get("https://www.mvideo.ru/sitebuilder/blocks/regionSelection.json.jsp?pageId=homepage&pageUrl=/&").json()
    log.info('Запрос страницы городов')
    html = lxml.html.fromstring(r["htmlContent"])
    log.info('Получение html')
    for elem in html.xpath("//input[@name='/com/mvideo/domain/RegionSelectionFormHandler.cityId']"):
        city=elem.get("value")
        cities.append(city)
        log.info(city)
 
def all_parsing():
    for city in cities:
        r = requests.get("https://www.mvideo.ru/smartfony-i-svyaz/smartfony-205/f/page=" + str(1)+"?cityId="+str(city))
        log.info("Переход на 1 страницу города:"+city)
        html =get_html(r)
        count_list=html.xpath("//a[@class='c-pagination__num c-btn c-btn_white ']/text()")[0]
        log.info("Парсинг")
        log.info(count_list)
        for i in range(1,int(count_list)+1):
            parameters=[]
            parameters.append("https://www.mvideo.ru/smartfony-i-svyaz/smartfony-205/f/page=" + str(i)+"?cityId="+city)
            parameters.append(city)
            q_list.append(parameters)


Добавлено через 1 минуту
Если посмотрите на код, то увидите закоментированные строчки в коде, на разные способы создания потоков/процессов
0
║XLR8║
 Аватар для outoftime
1212 / 909 / 270
Регистрация: 25.07.2009
Сообщений: 4,361
Записей в блоге: 5
13.04.2018, 16:56
Цитата Сообщение от danilshik Посмотреть сообщение
Не совсем понял. Вы хотите отправлять запросы async и все это в пуле?
Цитата Сообщение от danilshik Посмотреть сообщение
Все это в нескольких потоках, процессах.
Цитата Сообщение от outoftime Посмотреть сообщение
Вы начинаете асинхронно выкачивать данные
Вникай

Цитата Сообщение от danilshik Посмотреть сообщение
Если посмотрите на код
Не хочу я на него смотреть, код ужасный, форматирования нет, PEP8 писали специально для Вас.
0
Эксперт Python
5439 / 3860 / 1215
Регистрация: 28.10.2013
Сообщений: 9,552
Записей в блоге: 1
13.04.2018, 17:44
Цитата Сообщение от danilshik Посмотреть сообщение
почему то request+threedpoolexecutor в 10 потоков выполняется в 2 раза быстрее чем async с семафором 10
Потому что два ваших кода не сопоставимы между собой по логике. (Про необходимость следования PEP8 тоже не лишнее было указание).
Просто подсчитайте какое число корутин у вас запускается в асинхронном коде. Оно куда больше 10. Поэтому семафор с ограничением на 10 дает бОльшую задержку. Есть выставить в семафор любое большое число (безлимит) - асинхронный код должен стать быстрее многопоточного.
0
4 / 4 / 2
Регистрация: 04.04.2015
Сообщений: 186
13.04.2018, 18:13  [ТС]
Цитата Сообщение от Garry Galler Посмотреть сообщение
Просто подсчитайте какое число корутин у вас запускается в асинхронном коде. Оно куда больше 10. Поэтому семафор с ограничением на 10 дает бОльшую задержку. Есть выставить в семафор любое большое число (безлимит) - асинхронный код должен стать быстрее многопоточного.
Тут возникает 2 проблемы, если указать большое число
1. ошибка raise asyncio.TimeoutError from None concurrent.futures._base.TimeoutError, как я понял, это ошибка timeout запросов.
2. максимальное количество запросов, которые мы можем отправить серверу, чтобы не получить бан.
И в вопросе имелось ввиду некоторого ограничения, которые постоянно будет действовать, в данном случае макс. количество запросов.
0
Эксперт Python
5439 / 3860 / 1215
Регистрация: 28.10.2013
Сообщений: 9,552
Записей в блоге: 1
13.04.2018, 19:37
За asyncio.TimeoutError сказать ничего не могу - она возникает у меня только если я сам задам timeout (например 1\10 или 1\100 секунды для запроса страницы). По дефолту там не помню сколько, но достаточно много.
А по семафору, как я уже писал, вы неверно приравниваете выполнение 10 потоков (и фиг знает сколько заданий внутри них) и 10 корутин. Это не одно и тоже.

P.S. Советую полностью отрефакторить код - он реально трудночитаемый и вчитываться в него мало кому интересно.
Все url, селекторы и прочие строки не харкодятся в функциях, а определяются в переменных. В функциях нужно использовать переменные вместо строк. Пробелы. Код без пробелов - это ужас.
0
║XLR8║
 Аватар для outoftime
1212 / 909 / 270
Регистрация: 25.07.2009
Сообщений: 4,361
Записей в блоге: 5
14.04.2018, 16:09
Garry Galler, ТС-у надо весь курс вычитать с нуля, чтобы он понял в чем проблема с его "замерами". Вам надо либо самому вычитать его либо послать RTFM.
0
4 / 4 / 2
Регистрация: 04.04.2015
Сообщений: 186
19.04.2018, 19:39  [ТС]
Вообщем для себя я сделал такие выводы: в случае если есть какое то ограничение, например некоторое максимальное количество запросов для сервера, все же лучше использовать concurrent.futures+request. В случае если ограничение не маленькое, либо его вовсе нет, то лучше asyncio
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
19.04.2018, 19:39

В чем проблема? (Beautiful Soup)
from bs4 import BeautifulSoup import requests headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)...

Парсинг Beautiful Soup 4 и Selenium.Webdriver
Здравствуйте, пишу парсер под сайт https://www.kimovil.com/ru/ и возникает проблема: товары динамически подгружаются. Сначала были...

Beautiful Soup - существует ли ограничения на длину получаемых данных?
Здравствуйте! Почему при парсинге html достается только часть данных, которые все лежат в одном теге. данные - это 1 000 000 цифр. Получаю...

Извлечь атрибуты a href и img src одновременно, используя Beautiful Soup
Знаю как извлечь и показать a href urls = soup.findAll('a') for url in urls: print(url) Но как можно найти...

Как убрать soup = BeautifulSoup (html) из кода?
Приветствую всех, только недавно начал изучать Python, дали задание: сделать парс расписания нашей группы в универе. Пользовался Beautiful...


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

Или воспользуйтесь поиском по форуму:
48
Ответ Создать тему
Новые блоги и статьи
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru