Поисковик слов на страницах сайта. Нужна помощь в оптимизации кода

Всем привет. Захотел написать скрипт, который будет брать список сайтов, заходить на каждый, смотреть первую страницу и искать на ней какие-то нужные мне слова, и если найдет, то добавлять эти сайты в список результатов

Есть 2 проблемы и 2 вопроса:

  1. На сколь угодно значимом размере этого списка (скажем, 100+ сайтов и 20+ слов) код работает медленно. Какие есть варианты ускорить процесс?

  2. Т.к. я ищу в текстовом представлении страницы, то могут найтись значения, находящиеся внутри тегов, что мне совсем не нужно. Искать нужно только среди текста, представленного непосредственно на странице, а этих слов может среди них не оказаться. Как можно настроить поиск нужным мне способом?

Ниже сам код:

import requests
import re


masks = ['раскраск', 'game', 'играть', 'детск', 'кроссворд']
#  result_2 = []
checked = 0
errors = 0

with open('websites.txt', 'r') as websites, open('result.txt', 'w') as result:

    for site in websites:
        if 'youtube' in site.lower():
            continue
        try:
            page = requests.get(site.strip())
        except:
            errors += 1
            continue
        if any(mask in page.text for mask in masks):
            checked += 1
            #  print(site.strip())
            result.write(site.strip() + '\n')

print('Проверено сайтов: ', checked)
print('Ошибок: ', errors)

Пример файла с сайтами по Ссылке

И бонусный, более общий вопрос. Возможно существует более эффективный способ определить тематику сайта?


Ответы (1 шт):

Автор решения: Arty

Реализовал ваш алгоритм, код полностью по новому переписал.

Алгоритм многопоточный, 20 потоков задал, внутри ThreadPool(20), у меня для вашего входного websites.txt файла отработало за несколько секунд. Для парсинга и поска в HTML использовал BeautifulSoup.

Для использования кода нужно установить некоторые PIP модули через python -m pip install requests bs4 lxml.

Входные слова я вначале конвертирую в регулярные выражения через re.compile() так что можно в качестве слов любые регулярки использовать.

Результатом алгоритма является выходной websites.res.json, в нём для каждого сайта указано true/false (найдено/не-найдено) либо строка с сообщением об ошибке. Выход может быть не сортирован, т.к. я обрабатываю сайты для быстроты не в строгом порядке.

Попробовать онлайн!

import multiprocessing.pool, requests, bs4, lxml, re, json

words = ['раскраск', 'game', 'играть', 'детск', 'кроссворд']
words = [re.compile(w) for w in words]
with open('websites.txt', 'r', encoding = 'utf-8') as f:
    urls = [line.strip() for line in f if line.strip()]
def Match(url):
    try:
        text = requests.get(url).text
        soup = bs4.BeautifulSoup(text, 'lxml')
        for word in words:
            if len(soup(text = word)) > 0:
                return url, True
        return url, False
    except Exception as ex:
        return url, str(ex)
    finally:
        print('.', end = '', flush = True)
with multiprocessing.pool.ThreadPool(20) as pool:
    d = dict(list(pool.imap_unordered(Match, urls)))
with open('websites.res.json', 'w', encoding = 'utf-8') as f:
    f.write(json.dumps(d, indent = 4))

Вход (websites.txt):

http://zentut.info
http://avito.ru
http://killernews.ru
http://znanija.org
http://trashbox.ru
http://makefrag.ru
http://mybuses.ru
http://otzovik.com
http://scanword.org
http://witchhut.com
http://fortnitefun.ru
http://russian7.ru
http://skazkiwsem.ru
http://stolica-s.su
http://ukrtvory.ru
http://yesasia.ru
http://allforchildren.ru
http://allcalc.ru
http://ampproject.org
http://braintos.com
http://bugaga.ru
http://calc.ru
http://canlidizihd8.com
http://c-cafe.ru
http://classes.ru
http://comboplayer.ru
http://deadsouls.ru
http://fanfics.me

Выход (websites.res.json):

{
    "http://otzovik.com": false,
    "http://scanword.org": true,
    "http://fortnitefun.ru": true,
    "http://ukrtvory.ru": false,
    "http://russian7.ru": false,
    "http://witchhut.com": true,
    "http://braintos.com": true,
    "http://c-cafe.ru": true,
    "http://deadsouls.ru": false,
    "http://mybuses.ru": false,
    "http://allcalc.ru": false,
    "http://killernews.ru": false,
    "http://canlidizihd8.com": false,
    "http://bugaga.ru": false,
    "http://classes.ru": false,
    "http://makefrag.ru": true,
    "http://fanfics.me": false,
    "http://zentut.info": false,
    "http://stolica-s.su": true,
    "http://comboplayer.ru": false,
    "http://avito.ru": false,
    "http://yesasia.ru": false,
    "http://ampproject.org": false,
    "http://calc.ru": true,
    "http://skazkiwsem.ru": true,
    "http://allforchildren.ru": true,
    "http://trashbox.ru": true,
    "http://znanija.org": false
}
→ Ссылка