#python-2.7 #web-scraping
#python-2.7 #очистка веб-страниц
Вопрос:
Я новичок в Python и очень впечатлен количеством библиотек в моем распоряжении. У меня уже есть функция, которая использует Beautiful Soup для извлечения URL-адресов с сайта, но не все из них актуальны. Мне нужны только веб-страницы (без носителей) на том же веб-сайте (домен или поддомен, но никаких других доменов). Я пытаюсь вручную программировать примеры, с которыми сталкиваюсь, но чувствую, что изобретаю велосипед заново — конечно, это распространенная проблема в интернет-приложениях.
Вот примерный список URL-адресов, которые я мог бы получить с веб-сайта, скажем http://example.com , с пометками о том, нужны они мне или нет и почему. Надеюсь, это иллюстрирует проблему.
Хорошо:
example.com/page
— он ссылается на другую страницу в том же доменеexample.com/page.html
— имеет окончание типа файла, но это HTML-страницаsubdomain.example.com/page.html
— он находится на том же сайте, хотя и на поддомене/about/us
— это относительная ссылка, поэтому у нее нет домена, но это подразумевается
Плохо:
otherexample.com/page
— плохо, домен не соответствуетexample.com/image.jpg
— плохо, не изображение, а не страница/
— плохо — иногда в теге «a» есть только косая черта, но это ссылка на страницу, на которой я уже нахожусь#anchor
— это тоже относительная ссылка, но она находится на той же странице, поэтому в ней нет необходимости
Я писал случаи в if
заявлениях для каждого из них … но должен быть лучший способ!
Редактировать: вот мой текущий код, который ничего не возвращает:
ignore_values = {"", "/"}
def desired_links(href):
# ignore if href is not set
if not href:
return False
# ignore if it is just a link to the same page
if href.startswith("#"):
return False
# skip ignored values
if href in ignore_values:
return False
def explorePage(pageURL):
#Get web page
opener = urllib2.build_opener()
opener.addheaders = [('User-Agent', 'Mozilla/5.0')]
response = opener.open(pageURL)
html = response.read()
#Parse web page for links
soup = BeautifulSoup(html, 'html.parser')
links = [a["href"] for a in soup.find_all("a", href=desired_links)]
for link in links:
print(link)
return
def main():
explorePage("http://xkcd.com")
Комментарии:
1. Вам просто нужно создать некоторые правила и применить их к каждой ссылке
2. Это то, что я делал — игнорируйте, если это просто косая черта … удалите http: //, если он существует, и убедитесь, что он говорит example.com перед первой косой чертой, в противном случае игнорируйте … удалите все # и все, что следует за ним, если оно теперь пустое, то ignore…is выписывая их вручнуюединственный способ сделать это? Нет библиотек, которые могли бы помочь?
3. Большой шаг к фильтрации будет
soup.select("a[href*=example.com]")
4. Оооо, вот это действительно здорово. Спасибо!!
Ответ №1:
BeautifulSoup
довольно гибко помогает вам создавать и применять правила к значениям атрибутов. Вы можете создать функцию фильтрации и использовать ее в качестве значения для href
аргумента to find_all()
.
Например, что-то для вас, с чего можно начать:
ignore_values = {"", "/"}
def desired_links(href):
# ignore if href is not set
if not href:
return False
# ignore if it is just a link to the same page
if href.startswith("#"):
return False
# skip ignored values
if href in ignore_values:
return False
# TODO: more rules
# you would probably need "urlparse" package for a proper url analysis
return True
Использование:
links = [a["href"] for a in soup.find_all("a", href=desired_links)]
Вам следует взглянуть на Scrapy
и его Экстракторы ссылок.
Комментарии:
1. Это потрясающе. Чувак, в Python есть самые крутые вещи. Однако у меня есть несколько вопросов — во-первых, в href есть «if ‘#», но иногда на сайте есть ссылки на другие страницы (действительные), в которых просто есть теги привязки. Итак, я хочу игнорировать только теги привязки, поэтому, я думаю, просто удалите их? Похоже, что это будет игнорировать любой URL-адрес с # в нем, верно?
2. @Jake да, хороший улов, эту часть нужно улучшить, чтобы учитывать только текущую страницу.
3.
if not href.startswith("#")
вероятно, это сработает, или,if not href.startswith("#") or not href.endswith(("#", ".png", ".jpg"))
возможно, вы можете передать кортеж аргументов как endswith, так и startswith4. Я только что обновил свой вопрос с помощью некоторого примера кода, в значительной степени основанного на том, что здесь есть — к сожалению, он ничего не возвращает — есть идеи, почему?
5. @Jake конечно, у вас есть функция
return True
in в конце функции?