Как улучшить логику веб-сканера? - PullRequest
0 голосов
/ 20 марта 2019

Я работаю над веб-сканером, который будет сканировать только внутренние ссылки, используя запросы и bs4.

Ниже приведена грубая рабочая версия, но я не уверен, как правильно обрабатывать проверку того, была ли ссылка сканирована ранее или нет.

import re
import time
import requests
import argparse
from bs4 import BeautifulSoup


internal_links = set()

def crawler(new_link):


    html = requests.get(new_link).text 
    soup = BeautifulSoup(html, "html.parser")
    for link in soup.find_all('a', attrs={'href': re.compile("^http://")}):
        if "href" in link.attrs:
            print(link)
            if link.attrs["href"] not in internal_links:
                new_link = link.attrs["href"]
                print(new_link)
                internal_links.add(new_link)
                print("All links found so far, ", internal_links)
                time.sleep(6)
                crawler(new_link)


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('url', help='Pass the website url you wish to crawl')
    args = parser.parse_args()

    url = args.url

    #Check full url has been passed otherwise requests will throw error later

    try:
        crawler(url)

    except:
        if url[0:4] != 'http':
            print('Please try again and pass the full url eg http://example.com')



if __name__ == '__main__':
    main()

Это последние несколько строк вывода:

All links found so far,  {'http://quotes.toscrape.com/tableful', 'http://quotes.toscrape.com', 'http://quotes.toscrape.com/js', 'http://quotes.toscrape.com/scroll', 'http://quotes.toscrape.com/login', 'http://books.toscrape.com', 'http://quotes.toscrape.com/'}
<a href="http://quotes.toscrape.com/search.aspx">ViewState</a>
http://quotes.toscrape.com/search.aspx
All links found so far,  {'http://quotes.toscrape.com/tableful', 'http://quotes.toscrape.com', 'http://quotes.toscrape.com/js', 'http://quotes.toscrape.com/search.aspx', 'http://quotes.toscrape.com/scroll', 'http://quotes.toscrape.com/login', 'http://books.toscrape.com', 'http://quotes.toscrape.com/'}
<a href="http://quotes.toscrape.com/random">Random</a>
http://quotes.toscrape.com/random
All links found so far,  {'http://quotes.toscrape.com/tableful', 'http://quotes.toscrape.com', 'http://quotes.toscrape.com/js', 'http://quotes.toscrape.com/search.aspx', 'http://quotes.toscrape.com/scroll', 'http://quotes.toscrape.com/random', 'http://quotes.toscrape.com/login', 'http://books.toscrape.com', 'http://quotes.toscrape.com/'}

так что он работает, но только до определенного момента, а затем, кажется, больше не переходит по ссылкам.

Я уверен, что из-за этой строки

for link in soup.find_all('a', attrs={'href': re.compile("^http://")}):

, так как при этом будут найдены только ссылки, начинающиеся с http, и на многих внутренних страницах ссылки отсутствуют, но когда я пробую это так,

for link in soup.find_all('a')

программа запускается очень быстро и затем заканчивается:

http://books.toscrape.com
{'href': 'http://books.toscrape.com'}
http://books.toscrape.com
All links found so far,  {'http://books.toscrape.com'}
index.html
{'href': 'index.html'}
index.html
All links found so far,  {'index.html', 'http://books.toscrape.com'}

1 Ответ

1 голос
/ 20 марта 2019

Вы можете уменьшить

for link in soup.find_all('a', attrs={'href': re.compile("^http://")}):
        if "href" in link.attrs:
            print(link)
            if link.attrs["href"] not in internal_links:
                new_link = link.attrs["href"]
                print(new_link)
                internal_links.add(new_link)

Для

links = {link['href'] for link in soup.select("a[href^='http:']")}
internal_links.update(links)  

При этом используются только захваты, квалифицирующие элементы тега с протоколом http, и используется понимание набора, чтобы гарантировать отсутствие ошибок. Затем обновляет существующий набор новыми ссылками. Я не знаю достаточно Python, чтобы прокомментировать эффективность использования .update, но я считаю, что он изменяет существующий набор, а не создает новый. Другие методы объединения наборов перечислены здесь: Как объединить два набора в одну строку, не используя «|»

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