Траверс дерева в Python - PullRequest
0 голосов
/ 07 января 2020

Я пытаюсь написать скрипт для поиска неотвечающих ссылок на веб-странице в python. При попытке выяснить, что python не поддерживает многодетные узлы. Это правда? или мы можем получить доступ к дочерним узлам с несколькими дочерними узлами.

Ниже приведен фрагмент моего кода:

import httplib2
import requests
from bs4 import BeautifulSoup, SoupStrainer

status = {}
response = {}
output = {}

def get_url_status(url, count):
    global links
    links = []
    print(url)
    print(count)
    if count == 0:
        return output
    else:
        # if url not in output.keys():
        headers = requests.utils.default_headers()
        req = requests.get(url, headers)
        if('200' in str(req)):
            # if url not in output.keys():
            output[url] = '200';
            for link in BeautifulSoup(req.content, parse_only=SoupStrainer('a')):
                if 'href' in str(link):
                    links.append(link.get('href'))

            # removing other non-mandotary links
            for link in links[:]:
                if "mi" not in link:
                    links.remove(link)

            # removing same url
            for link in links[:]:
                if link.rstrip('/') == url:
                    links.remove(link)

            # removing duplicate links
            links = list(dict.fromkeys(links))
            if len(links) > 0:
                for urllink in links:
                    return get_url_status(urllink, count-1)

result = get_url_status('https://www.mi.com/in', 5)
print(result)

В этом коде он распространяется только на левые узлы дочернего узла и пропускает остальные. что-то вроде этого. enter image description here

И выходной сигнал неудовлетворительный и очень очень низкий по сравнению с реальным.

{'https://www.mi.com/in': '200', 'https://in.c.mi.com/': '200', 'https://in.c.mi.com/index.php': '200', 'https://in.c.mi.com/global/': '200', 'https://c.mi.com/index.php': '200'}

Я знаю, мне не хватает во многих местах, но я Я никогда не делал что-то такого масштаба, и это мой первый раз. Так что извините, если это вопрос новичка.

Примечание: я использовал mi.com только для справки.

1 Ответ

1 голос
/ 07 января 2020

На первый взгляд, есть одна очевидная проблема.

if len(links) > 0:
    for urllink in links:
        return get_url_status(urllink, count-1)

Этот фрагмент не выполняет итерацию по links. Он имеет return в своем итеративном теле, что означает, что он будет работать только для первого элемента в ссылках и немедленно вернет его. Есть еще одна ошибка. Функция возвращает просто None вместо output, если она встречает страницу без ссылок до того, как count достигнет 0. Вместо этого выполните следующее.

if len(links):
    for urllink in links:
        get_url_status(urllink, count-1)
return output

И if('200' in str(req)) не правильный путь проверить код состояния. Он будет проверять наличие подстроки '200' в теле, а не только проверять код состояния. Это должно быть if req.status_code == 200.

Другое дело, что функция добавляет только отзывчивые ссылки на output. Если вы хотите проверить наличие неотвечающих ссылок, не нужно ли добавлять ссылки, которые не возвращают код состояния 200?

import requests
from bs4 import BeautifulSoup, SoupStrainer

status = {}
response = {}
output = {}

def get_url_status(url, count):
    global links
    links = []
    # if url not in output.keys():
    headers = requests.utils.default_headers()
    req = requests.get(url, headers)
    if req.status_code == 200:
        # if url not in output.keys():
        output[url] = '200'
        if count == 0:
            return output
        for link in BeautifulSoup(req.content, parse_only=SoupStrainer('a'), parser="html.parser"):
            if 'href' in str(link):
                links.append(link.get('href'))

        # removing other non-mandotary links
        for link in links:
            if "mi" not in link:
                links.remove(link)

        # removing same url
        for link in links:
            if link.rstrip('/') == url:
                links.remove(link)

        # removing duplicate links
        links = list(dict.fromkeys(links))
        print(links)
        if len(links):
            for urllink in links:
                get_url_status(urllink, count-1)
        return output

result = get_url_status('https://www.mi.com/in', 1)
print(result)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...