Как быстро очистить многие документы HTML с помощью Python? - PullRequest
1 голос
/ 08 июля 2019

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

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

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

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

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

Ответы [ 3 ]

1 голос
/ 08 июля 2019

Быстрый поиск "асинхронной очистки в Python" привел к этой статье на среднем от Santhosh Hari. Пожалуйста, прочитайте эту статью, так как он объясняет, как работает код.

Суть статьи заключается в использовании библиотек 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)
1 голос
/ 08 июля 2019

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

Ex: PATH TITLE DIV IMAGE DIV BODY DIV

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

1 голос
/ 08 июля 2019

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

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

    return Soup_SomeSite.title.string

Создает в results список заголовков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...