Answer the question
In order to leave comments, you need to log in
Why doesn't the Python parser for all internal site links want to parse some sites?
Parser code:
from urllib.parse import urlparse
from bs4 import BeautifulSoup
import requests
import lxml
DOMAIN = 'apexair.ru'
HOST = 'http://' + DOMAIN
FORBIDDEN_PREFIXES = ['#', 'tel:', 'mailto:']
links = set() # множество всех ссылок
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
response = requests.get(HOST, headers=headers)
# print(response.content)
def add_all_links_recursive(url, maxdepth=1):
# print('{:>5}'.format(len(links)), url[len(HOST):])
# глубина рекурсии не более `maxdepth`
# список ссылок, от которых в конце мы рекурсивно запустимся
links_to_handle_recursive = []
# получаем html код страницы
request = requests.get(url, headers=headers)
# парсим его с помощью BeautifulSoup
soup = BeautifulSoup(request.content, 'lxml')
# рассматриваем все теги <a>
for tag_a in soup.find_all('a'):
link = tag_a['href']
# если ссылка не начинается с одного из запрещённых префиксов
if all(not link.startswith(prefix) for prefix in FORBIDDEN_PREFIXES):
# проверяем, является ли ссылка относительной
# например, `/oplata` --- это относительная ссылка
# `http://101-rosa.ru/oplata` --- это абсолютная ссылка
if link.startswith('/') and not link.startswith('//'):
# преобразуем относительную ссылку в абсолютную
link = HOST + link
# проверяем, что ссылка ведёт на нужный домен
# и что мы ещё не обрабатывали такую ссылку
if urlparse(link).netloc == DOMAIN and link not in links:
links.add(link)
links_to_handle_recursive.append(link)
if maxdepth > 0:
for link in links_to_handle_recursive:
add_all_links_recursive(link, maxdepth=maxdepth - 1)
def main():
add_all_links_recursive(HOST + '/')
for link in links:
print(link)
if __name__ == '__main__':
main()
Traceback (most recent call last):
File "E:/Users/Alex/Documents/MyPyProj/parser-links.py", line 57, in <module>
main()
File "E:/Users/Alex/Documents/MyPyProj/parser-links.py", line 51, in main
add_all_links_recursive(HOST + '/')
File "E:/Users/Alex/Documents/MyPyProj/parser-links.py", line 47, in add_all_links_recursive
add_all_links_recursive(link, maxdepth=maxdepth - 1)
File "E:/Users/Alex/Documents/MyPyProj/parser-links.py", line 28, in add_all_links_recursive
link = tag_a['href']
File "C:\Python38\lib\site-packages\bs4\element.py", line 1321, in __getitem__
return self.attrs[key]
KeyError: 'href'
Answer the question
In order to leave comments, you need to log in
On every "a" tag there is a `href`.
from urllib.parse import urlparse
from bs4 import BeautifulSoup
import requests
import lxml
DOMAIN = 'apexair.ru'
HOST = 'http://' + DOMAIN
FORBIDDEN_PREFIXES = ['#', 'tel:', 'mailto:']
links = set() # множество всех ссылок
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
response = requests.get(HOST, headers=headers)
# print(response.content)
def add_all_links_recursive(url, maxdepth=1):
# print('{:>5}'.format(len(links)), url[len(HOST):])
# глубина рекурсии не более `maxdepth`
# список ссылок, от которых в конце мы рекурсивно запустимся
links_to_handle_recursive = []
# получаем html код страницы
request = requests.get(url, headers=headers)
# парсим его с помощью BeautifulSoup
soup = BeautifulSoup(request.content, 'lxml')
# рассматриваем все теги <a>
for tag_a in soup.find_all('a', href=lambda v: v is not None):
link = tag_a['href']
# если ссылка не начинается с одного из запрещённых префиксов
if all(not link.startswith(prefix) for prefix in FORBIDDEN_PREFIXES):
# проверяем, является ли ссылка относительной
# например, `/oplata` --- это относительная ссылка
# `http://101-rosa.ru/oplata` --- это абсолютная ссылка
if link.startswith('/') and not link.startswith('//'):
# преобразуем относительную ссылку в абсолютную
link = HOST + link
# проверяем, что ссылка ведёт на нужный домен
# и что мы ещё не обрабатывали такую ссылку
if urlparse(link).netloc == DOMAIN and link not in links:
links.add(link)
links_to_handle_recursive.append(link)
if maxdepth > 0:
for link in links_to_handle_recursive:
add_all_links_recursive(link, maxdepth=maxdepth - 1)
def main():
add_all_links_recursive(HOST + '/')
for link in links:
print(link)
if __name__ == '__main__':
main()
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question