Як створити сканер URL-адреси для відображення веб-сайту за допомогою Python

Простий проект для вивчення основ веб-вишкрібання

Перш ніж розпочати, давайте переконаймося, що ми розуміємо, що таке веб-скрапінг:

Веб-скрапінг - це процес вилучення даних з веб-сайтів для їх подання у форматі, який користувачі можуть легко зрозуміти.

У цьому підручнику я хочу продемонструвати, як легко створити простий сканер URL-адрес у Python, який можна використовувати для картографування веб-сайтів. Незважаючи на те, що ця програма відносно проста, вона може забезпечити чудове введення в основи веб-вишкрібання та автоматизації. Ми зосередимося на рекурсивному витягуванні посилань з веб-сторінок, але ті самі ідеї можуть бути застосовані до безлічі інших рішень.

Наша програма працюватиме так:

  1. Відвідайте веб-сторінку
  2. Викресліть усі унікальні URL-адреси, знайдені на веб-сторінці, і додайте їх до черги
  3. Рекурсивно обробляйте URL-адреси одну за одною, поки ми не вичерпаємо чергу
  4. Роздрукувати результати

Насамперед

Перше, що нам слід зробити, це імпортувати всі необхідні бібліотеки. Ми будемо використовувати BeautifulSoup, запити та urllib для веб-скрапінгу.

from bs4 import BeautifulSoupimport requestsimport requests.exceptionsfrom urllib.parse import urlsplitfrom urllib.parse import urlparsefrom collections import deque

Далі нам потрібно вибрати URL-адресу, з якої почнеться сканування. Хоча ви можете вибрати будь-яку веб-сторінку з HTML-посиланнями, я рекомендую використовувати ScrapeThisSite. Це безпечна пісочниця, по якій ви можете повзати, не потрапляючи в халепу.

url = “//scrapethissite.com”

Далі нам потрібно буде створити новий об'єкт deque, щоб ми могли легко додавати нещодавно знайдені посилання та видаляти їх, коли закінчимо їх обробляти. Попередньо заповніть deque вашою urlзмінною:

# a queue of urls to be crawled nextnew_urls = deque([url])

Потім ми можемо використовувати набір для зберігання унікальних URL-адрес після їх обробки:

# a set of urls that we have already processed processed_urls = set()

Ми також хочемо відстежувати місцеві (той самий домен, що і цільовий), закордонний (інший домен, як цільовий), і непрацюючі URL-адреси:

# a set of domains inside the target websitelocal_urls = set()
# a set of domains outside the target websiteforeign_urls = set()
# a set of broken urlsbroken_urls = set()

Час повзати

З усім цим на місці, тепер ми можемо почати писати власне код для сканування веб-сайту.

Ми хочемо переглянути кожну URL-адресу в черзі, перевірити, чи є на цій сторінці додаткові URL-адреси, і додати кожну з них у кінець черги, поки не залишиться жодної. Як тільки ми закінчимо зішкрібати URL-адресу, ми вилучимо її з черги та додамо до processed_urlsнабору для подальшого використання.

# process urls one by one until we exhaust the queuewhile len(new_urls): # move url from the queue to processed url set url = new_urls.popleft() processed_urls.add(url) # print the current url print(“Processing %s” % url)

Далі додайте виняток, щоб зловити будь-які непрацездатні веб-сторінки та додайте їх до broken_urlsнабору для подальшого використання:

try: response = requests.get(url)
except(requests.exceptions.MissingSchema, requests.exceptions.ConnectionError, requests.exceptions.InvalidURL, requests.exceptions.InvalidSchema): # add broken urls to it’s own set, then continue broken_urls.add(url) continue

Потім нам потрібно отримати базову URL-адресу веб-сторінки, щоб ми могли легко диференціювати місцеві та іноземні адреси:

# extract base url to resolve relative linksparts = urlsplit(url)base = “{0.netloc}”.format(parts)strip_base = base.replace(“www.”, “”)base_url = “{0.scheme}://{0.netloc}”.format(parts)path = url[:url.rfind(‘/’)+1] if ‘/’ in parts.path else url

Ініціалізуйте BeautifulSoup для обробки документа HTML:

soup = BeautifulSoup(response.text, “lxml”)

Тепер зішкребіть веб-сторінку для всіх посилань та відсортуйте, додайте їх до відповідного набору:

for link in soup.find_all(‘a’): # extract link url from the anchor anchor = link.attrs[“href”] if “href” in link.attrs else ‘’
if anchor.startswith(‘/’): local_link = base_url + anchor local_urls.add(local_link) elif strip_base in anchor: local_urls.add(anchor) elif not anchor.startswith(‘http’): local_link = path + anchor local_urls.add(local_link) else: foreign_urls.add(anchor)

Оскільки я хочу обмежити свій сканер лише локальними адресами, я додаю наступне, щоб додати нові URL-адреси до нашої черги:

for i in local_urls: if not i in new_urls and not i in processed_urls: new_urls.append(i)

Якщо ви хочете просканувати всі URL-адреси, використовуйте:

if not link in new_urls and not link in processed_urls: new_urls.append(link)

Попередження: Те, як зараз працює програма, сканування іноземних URL-адрес займе ДУЖЕ довго. Можливо, у вас можуть виникнути проблеми з витиранням веб-сайтів без дозволу. Використовуйте на свій страх і ризик!

Ось весь мій код:

І це повинно бути все. Ви щойно створили простий інструмент для сканування веб-сайту та відображення всіх знайдених URL-адрес!

На завершення

Не соромтеся створювати та вдосконалювати цей код. Наприклад, ви можете змінити програму для пошуку на веб-сторінках адрес електронної пошти або номерів телефонів під час їх сканування. Ви навіть можете розширити функціональність, додавши аргументи командного рядка, надаючи можливість визначати вихідні файли, обмежувати пошук глибиною та багато іншого. Дізнайтеся про те, як створити інтерфейси командного рядка для прийняття аргументів тут.

Якщо у вас є додаткові рекомендації, поради чи ресурси, будь ласка, поділіться з ними у коментарях!

Дякуємо за читання! Якщо вам сподобався цей підручник і ви хочете отримати більше подібного вмісту, обов’язково розіб’йте цю кнопку слідування. ❤️

Також обов’язково перевірте мій веб-сайт, Twitter, LinkedIn та Github.