Как быстро очистить множество HTML-документов с помощью Python?

У меня есть список из примерно 100 веб-страниц HTML (все они имеют разные структуры, такие как div, привязки, классы и т. д.), и я пытаюсь очистить заголовок каждой страницы (где заголовок находится под определенным div и классом). Для этого я использовал запросы на получение и Beautifulsoup, однако это занимает много времени (10 минут каждый раз, когда я хочу это сделать)!

Я использовал таймер, чтобы увидеть, что занимает больше всего времени: это запросы на получение. Судя по всему, Python (3.7) выполняет код один за другим, и, поскольку каждый запрос на получение занимает около 5-6 секунд, для выполнения ~ 100 запросов требуется примерно 500-600 секунд.

Я искал способы заставить эти запросы работать быстрее и наткнулся на множество различных решений. Тем не менее, общая тема, похоже, заключалась в том, что асинхронность моих запросов (чтобы все запросы запускались одновременно) решит проблему (за счет ускорения).

Для этого было много возможных решений, которые я читал в Интернете, в том числе: многопоточность, использование grequest, использование Scrapy, синтаксический анализ lxml и т. д. Однако я новичок в программировании и недостаточно квалифицирован, чтобы учиться и экспериментировать с каждым способом (на самом деле , я пытался следовать ответам на подобные вопросы на SO, но безуспешно), поэтому я не уверен, какой маршрут мне лучше выбрать.

Мне не нужно ничего необычного; все, что я хочу сделать, это извлечь заголовки из документов HTML в виде текста, а затем распечатать их. Мне не нужно загружать какие-либо файлы CSS, изображения, мультимедиа и т. д. Кроме того, я надеюсь, что код будет как можно более простым/голым. Как я могу сделать это как можно быстрее в Python? Я был бы признателен, если бы кто-нибудь мог предложить лучший путь (например, с использованием Scrapy) и дать краткое объяснение того, что я должен делать с помощью этого инструмента, чтобы получить результаты, на которые я надеюсь. Вам не нужно писать весь код для меня. Спасибо!

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
152
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

У Этот ответ, похоже, есть готовый для вырезания и вставки ответ. (Вы также, вероятно, могли бы увеличить размер пула потоков, если ваш HTML-запрос занимает около 5 секунд.) Для вашей точной проблемы код:

def crawlToCSV(URLrecord):
    OpenSomeSiteURL = urllib2.urlopen(URLrecord)
    Soup_SomeSite = BeautifulSoup(OpenSomeSiteURL, "lxml")
    OpenSomeSiteURL.close()

    return Soup_SomeSite.title.string

Создал бы в results список заголовков.

Быстрый поиск «асинхронного парсинга в python» привел к эта статья на медиуме Сантоша Хари. Пожалуйста, прочитайте эту статью, поскольку он дает объяснение того, как работает код.

Суть поста в следующем: используются библиотеки asyncio и aiohttp.

import asyncio
import aiohttp
import requests

async def fetch_url(session, url):
    async with session.get(url, timeout=60 * 60) as response:
        return await response.text()

async def fetch_all_urls(session, urls, loop):
    results = await asyncio.gather(*[fetch_url(session, url) for url in urls],
    return_exceptions=True)
    return results

def get_htmls(urls):
    if len(urls) > 1:
        loop = asyncio.get_event_loop()
        connector = aiohttp.TCPConnector(limit=100)
        with aiohttp.ClientSession(loop=loop, connector=connector) as session:
            htmls = loop.run_until_complete(fetch_all_urls(session, urls, loop))
        raw_result = dict(zip(urls, htmls))
    else:
        headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'}
        raw_result = requests.get(urls[0], headers=headers).text

    return raw_result

result_dict = get_htmls(url_list)

loop в этой функции fetch_all_urls(session, urls, loop) просто заполнитель и абсолютно ничего не делает, не так ли?

MITHU 08.07.2019 12:58

Одна из идей, которую я могу предложить, заключается в том, чтобы взять все URL-адреса в Csv и сохранить несколько заголовков, таких как path, title div, body div, div image в соответствии с вашими требованиями, и продолжать добавлять конкретный div (div class="title").

Бывший: ПУТЬ НАЗВАНИЕ РАЗДЕЛ ИЗОБРАЖЕНИЯ РАЗДЕЛ ТЕЛА РАЗДЕЛ

Точно так же вы можете указать все ссылки в одном CSV-файле и прочитать его через скрипт Python, чтобы все данные были извлечены.

Другие вопросы по теме