Parser

mail@pastecode.io avatar
unknown
python
2 years ago
3.6 kB
11
Indexable
Never
# Задание
# Сколько HTML-тегов в коде главной страницы сайта google.com?
# Сколько из них содержит атрибуты?

# Напишите скрипт на Python, который выводит ответы на вопросы выше.
# Скрипт должен быть в виде одного модуля .py

import os
from html.parser import HTMLParser

import requests
import validators

# Аннотация для Ментора
# Просьба не обращать внимания на данный класс, с ним все в порядке
class Parser(HTMLParser):
    """Find HTML-tags and call handler methods."""

    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        self.start_tags = []
        self.tags_has_attrs = []
        self.end_tags = []

    def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
        if attrs:
            self.tags_has_attrs.append(tag)
        self.start_tags.append(tag)

    def handle_endtag(self, tag: str) -> None:
        self.end_tags.append(tag)


def clear_terminal() -> None:
    os.system('cls||clear')


def get_user_input() -> str:
    how_to_use = '''
    Enter url or domain name of site you want to parse.
    
    Examples:
            google.com
            www.google.com/
            https://google.com
            http://www.google.com/
            
    If nothing is entered, the google.com site will be parse.

    Site address to parse (default: google.com): '''

    # Remove spaces and '/' at the end
    user_input = input(how_to_use).strip().rstrip('/')

    if not user_input:
        return 'https://google.com'

    return user_input


def check_user_input(user_input: str) -> str:
    protocols = ('https://', 'http://')

    # Check user_input starts with protocols
    if not user_input.startswith(protocols):
        user_input = protocols[0] + user_input

    if validators.url(user_input):
        return user_input

    clear_terminal()
    raise SystemExit(f'<{user_input}> is not valid URL')


def get_response(url: str) -> 'Response':
    try:
        response = requests.get(url, timeout=5)
        # Raise HTTPError exception if Request returned an unsuccessful status code (4xx/5xx)
        response.raise_for_status()
    except (requests.exceptions.HTTPError,
            requests.exceptions.ConnectionError,
            requests.exceptions.Timeout,
            requests.exceptions.RequestException) as error:
        clear_terminal()
        raise SystemExit(error)

    return response


def parse_data(response: 'Response') -> Parser:
    parser = Parser()

    # Data to feed in parser should be str
    parser.feed(response.text)

    return parser


def print_parsed_data(parsed_data: Parser) -> None:
    count_of_start_tags = len(parsed_data.start_tags)
    count_of_tags_has_attrs = len(parsed_data.tags_has_attrs)
    count_of_end_tags = len(parsed_data.end_tags)
    all_tags = count_of_start_tags + count_of_end_tags
    clear_terminal()

    print(f'''
    Count of start tags (eg <h1>): {count_of_start_tags}
    Count of tags has attrs (eg <h1 class="">): {count_of_tags_has_attrs}
    Count of end tags (eg </h1>): {count_of_end_tags}

    Amount of HTML-tags: {all_tags}
    ''')


def start_script() -> None:
    user_input = get_user_input()
    url = check_user_input(user_input)
    response = get_response(url)
    parsed_data = parse_data(response)
    print_parsed_data(parsed_data)


if __name__ == '__main__':
    start_script()