Извлечение всех URL-адресов веб-страниц в том же домене, но без носителей или привязок

#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, так и startswith

4. Я только что обновил свой вопрос с помощью некоторого примера кода, в значительной степени основанного на том, что здесь есть — к сожалению, он ничего не возвращает — есть идеи, почему?

5. @Jake конечно, у вас есть функция return True in в конце функции?