получить ссылки с веб-страницы, используя python и BeautifulSoup

Как я могу получить ссылки на веб-странице и скопировать URL-адрес ссылок, используя Python?

Ответы на вопрос(14)

import urllib2
url="http://www.somewhere.com"
page=urllib2.urlopen(url)
data=page.read().split("</a>")
tag="<a href=\""
endtag="\">"
for item in data:
    if "<a href" in item:
        try:
            ind = item.index(tag)
            item=item[ind+len(tag):]
            end=item.index(endtag)
        except: pass
        else:
            print item[:end]

для более сложных операций, конечно, BSoup все еще предпочтителен.

 nwgat25 апр. 2017 г., 02:18
есть ли способ отфильтровать только некоторые ссылки с этим? как, скажем, я хочу только ссылки, которые имеют "Эпизод" в ссылке?
 dimo41412 сент. 2012 г., 23:28
А если, например, есть что-то среднее между<a а такжеhref? Сказатьrel="nofollow" илиonclick="..." или просто новая строка? / Stackoverflow.com вопросы / 1732348 / ...

что вы ищете, но также разрешает относительные ссылки на абсолютные ссылки.

import urllib
import lxml.html
import urlparse

def get_dom(url):
    connection = urllib.urlopen(url)
    return lxml.html.fromstring(connection.read())

def get_links(url):
    return resolve_links((link for link in get_dom(url).xpath('//a/@href')))

def guess_root(links):
    for link in links:
        if link.startswith('http'):
            parsed_link = urlparse.urlparse(link)
            scheme = parsed_link.scheme + '://'
            netloc = parsed_link.netloc
            return scheme + netloc

def resolve_links(links):
    root = guess_root(links)
    for link in links:
        if not link.startswith('http'):
            link = urlparse.urljoin(root, link)
        yield link  

for link in get_links('http://www.google.com'):
    print link
Решение Вопроса

lSoup:

import httplib2
from BeautifulSoup import BeautifulSoup, SoupStrainer

http = httplib2.Http()
status, response = http.request('http://www.nytimes.com')

for link in BeautifulSoup(response, parse_only=SoupStrainer('a')):
    if link.has_attr('href'):
        print link['href']

Документация BeautifulSoup на самом деле довольно хорошая и охватывает ряд типичных сценариев:

http: //www.crummy.com/software/BeautifulSoup/documentation.htm

Редактировать: обратите внимание, что я использовал класс SoupStrainer, потому что он немного более эффективен (с точки зрения памяти и скорости), если вы знаете, что вы анализируете заранее.

 BenDundee19 февр. 2013 г., 15:11
Берегись:/usr/local/lib/python2.7/site-packages/bs4/__init__.py:128: UserWarning: The "parseOnlyThese" argument to the BeautifulSoup constructor has been renamed to "parse_only."
 Rishabh Agrahari11 мая 2017 г., 10:56
от bs4 import BeautifulSoup. (не из BeautifulSoup импортировать BeautifulSoup ..) требуется коррекция.
 user279611826 окт. 2013 г., 23:01
На версии 3.2.1 BeautifulSoup нетhas_attr. Вместо этого я вижу что-то под названиемhas_key и это работает.
 john doe06 апр. 2017 г., 06:59
Обновление для python3
 Evan Fosmark03 июл. 2009 г., 20:57
+ 1, использовать суповое ситечко - отличная идея, поскольку позволяет обойтись без ненужного анализа, когда все, что вам нужно, это ссылки.

LXML. Несмотря на название, он также предназначен для анализа и очистки HTML. Это намного, намного быстрее, чем BeautifulSoup, и он даже обрабатывает «сломанный» HTML лучше, чем BeautifulSoup (их претензия на известность). Он также имеет API совместимости для BeautifulSoup, если вы не хотите изучать lxml API.

Ян Бликинг соглашается.

Больше нет смысла использовать BeautifulSoup, если только вы не работаете в Google App Engine или где-то, где нет чисто Python.

lxml.html также поддерживает селекторы CSS3, так что подобные вещи тривиальны.

Пример с lxml и xpath будет выглядеть так:

import urllib
import lxml.html
connection = urllib.urlopen('http://www.nytimes.com')

dom =  lxml.html.fromstring(connection.read())

for link in dom.xpath('//a/@href'): # select the url in href for all a tags(links)
    print link
 Martijn Pieters♦28 дек. 2014 г., 13:29
BeautifulSoup 4 будет использоватьlxml как парсер по умолчанию, если установлен.

Чтобы найти все ссылки, в этом примере мы будем использовать модуль urllib2 вместе с re.module * Одной из самых мощных функций в модуле re является "re.findall ()". В то время как re.search () используется для поиска первого совпадения для шаблона, re.findall () находитвс совпадений и возвращает их в виде списка строк, где каждая строка представляет одно совпадение *


import re
#connect to a URL
website = urllib2.urlopen(url)

#read html code
html = website.read()

#use re.findall to get all the links
links = re.findall('"((http|ftp)s?://.*?)"', html)

print links

lxml и списочные списки делают убийственную комбинацию.

import requests
import lxml.html

dom = lxml.html.fromstring(requests.get('http://www.nytimes.com').content)

[x for x in dom.xpath('//a/@href') if '//' in x and 'nytimes.com' not in x]

В списке компонов «if '//» и «url.com» не в x »- это простой метод очистки списка URL-адресов« внутренних »URL-адресов сайтов и т. Д.

 dotancohen16 дек. 2013 г., 08:43
ОП не запрашивал эти функции, и часть, которую он запрашивал, уже была опубликована и решена с использованием того же метода, что и вы. Тем не менее, я уберу понижение рейтинга, так как понимание списка действительно приносит пользу людям, которым нужны эти функции, и вы явно упоминаете их в тексте поста. Также вы можете использовать rep:)
 cheekybastard16 дек. 2013 г., 00:30
Если это репост, почему оригинальное сообщение не содержит: 1. запросы 2. список комп 3. логика для очистки внутренних и нежелательных ссылок сайта ?? Попробуйте сравнить результаты двух постов, мой список отлично справляется с поиском ненужных ссылок.

Вот пример использования @ars принятого ответа иBeautifulSoup4, requests, а такжеwget модули для обработки загрузок.

import requests
import wget
import os

from bs4 import BeautifulSoup, SoupStrainer

url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/eeg-mld/eeg_full/'
file_type = '.tar.gz'

response = requests.get(url)

for link in BeautifulSoup(response.content, 'html.parser', parse_only=SoupStrainer('a')):
    if link.has_attr('href'):
        if file_type in link['href']:
            full_path = url + link['href']
            wget.download(full_path)

после следующего исправления (охватывающего сценарий, когда он не работал правильно):

for link in BeautifulSoup(response.content, 'html.parser', parse_only=SoupStrainer('a')):
    if link.has_attr('href'):
        if file_type in link['href']:
            full_path =urlparse.urljoin(url , link['href']) #module urlparse need to be imported
            wget.download(full_path)

Для Python 3:

urllib.parse.urljoinместо этого необходимо использовать @, чтобы получить полный URL.

было бы более целесообразно использовать LXML, который может анализировать непосредственно с URL (с некоторыми ограничениями, упомянутыми ниже).

import lxml.html

doc = lxml.html.parse(url)

links = doc.xpath('//a[@href]')

for link in links:
    print link.attrib['href']

Приведенный выше код вернет ссылки как есть, и в большинстве случаев они будут относительными или абсолютными из корня сайта. Поскольку мой вариант использования заключался в извлечении ссылок только определенного типа, ниже приведена версия, которая преобразует ссылки в полные URL-адреса и при необходимости принимает шаблон глобуса, например*.mp3. Он не будет обрабатывать одинарные и двойные точки в относительных путях, но пока у меня не было необходимости в этом. Если вам нужно разобрать фрагменты URL, содержащие../ или./ тогда Urlparse.urljoin может пригодиться.

НОТ: Прямой синтаксический анализ lxml не обрабатывает загрузку изhttps и не выполняет перенаправления, поэтому по этой причине в приведенной ниже версии используетсяurllib2 + lxml.

#!/usr/bin/env python
import sys
import urllib2
import urlparse
import lxml.html
import fnmatch

try:
    import urltools as urltools
except ImportError:
    sys.stderr.write('To normalize URLs run: `pip install urltools --user`')
    urltools = None


def get_host(url):
    p = urlparse.urlparse(url)
    return "{}://{}".format(p.scheme, p.netloc)


if __name__ == '__main__':
    url = sys.argv[1]
    host = get_host(url)
    glob_patt = len(sys.argv) > 2 and sys.argv[2] or '*'

    doc = lxml.html.parse(urllib2.urlopen(url))
    links = doc.xpath('//a[@href]')

    for link in links:
        href = link.attrib['href']

        if fnmatch.fnmatch(href, glob_patt):

            if not href.startswith(('http://', 'https://' 'ftp://')):

                if href.startswith('/'):
                    href = host + href
                else:
                    parent_url = url.rsplit('/', 1)[0]
                    href = urlparse.urljoin(parent_url, href)

                    if urltools:
                        href = urltools.normalize(href)

            print href

Использование выглядит следующим образом:

getlinks.py http://stackoverflow.com/a/37758066/191246
getlinks.py http://stackoverflow.com/a/37758066/191246 "*users*"
getlinks.py http://fakedomain.mu/somepage.html "*.mp3"
 ccpizza11 июн. 2016 г., 00:48
@ alexis: я думаюlxml.html немного мягче, чемlxml.etree. Если ваш ввод не правильно сформирован, вы можете явно установить синтаксический анализатор BeautifulSoup: Lxml.de / elementsoup.html. И если вы используете BeatifulSoup, тогда BS3 - лучший выбор.
 alexis11 июн. 2016 г., 00:41
lxml может обрабатывать только действительные данные, как он может заменитьBeautifulSoup?

версия BeautifulSoup 4, использующая также кодировку, предоставляемую сервером:

from bs4 import BeautifulSoup
import urllib2

resp = urllib2.urlopen("http://www.gpsbasecamp.com/national-parks")
soup = BeautifulSoup(resp, from_encoding=resp.info().getparam('charset'))

for link in soup.find_all('a', href=True):
    print link['href']

или версия Python 3:

from bs4 import BeautifulSoup
import urllib.request

resp = urllib.request.urlopen("http://www.gpsbasecamp.com/national-parks")
soup = BeautifulSoup(resp, from_encoding=resp.info().get_param('charset'))

for link in soup.find_all('a', href=True):
    print(link['href'])

и версия, использующаяrequests библиотека, который, как написано, будет работать в Python 2 и 3:

from bs4 import BeautifulSoup
from bs4.dammit import EncodingDetector
import requests

resp = requests.get("http://www.gpsbasecamp.com/national-parks")
http_encoding = resp.encoding if 'charset' in resp.headers.get('content-type', '').lower() else None
html_encoding = EncodingDetector.find_declared_encoding(resp.content, is_html=True)
encoding = html_encoding or http_encoding
soup = BeautifulSoup(resp.content, from_encoding=encoding)

for link in soup.find_all('a', href=True):
    print(link['href'])

Thesoup.find_all('a', href=True) вызов находит все<a> элементы, которые имеютhref атрибут; элементы без атрибута пропускаются.

BeautifulSoup 3 прекратил разработку в марте 2012 года; новые проекты действительно должны использовать BeautifulSoup 4, всегда.

Обратите внимание, что вы должны оставить декодирование HTML из байтов to BeautifulSoup. Вы можете сообщить BeautifulSoup о наборе символов, найденном в заголовках ответа HTTP, чтобы помочь в декодировании, но этоможе быть неправым и конфликтовать с<meta> информация заголовка находится в самом HTML, поэтому в приведенном выше примере используется метод внутреннего класса BeautifulSoupEncodingDetector.find_declared_encoding(), чтобы убедиться, что такие подсказки встроенной кодировки побеждают неправильно настроенный сервер.

Сrequests,response.encoding атрибут по умолчанию имеет значение Latin-1, если в ответе естьtext/* mimetype, даже если набор символов не был возвращен. Это согласуется с HTTP RFC, но болезненно при использовании с разбором HTML, поэтому вы должны игнорировать этот атрибут, когда нетcharset устанавливается в заголовке Content-Type.

 Martijn Pieters♦02 февр. 2017 г., 08:39
@ AnttiHaapala:SoupStrainer ты имеешь в виду? Это никуда не делась, это все еще часть проекта.
 Antti Haapala02 февр. 2017 г., 08:07
Есть ли что-то вроде StrainedSoup для bs4? (Мне это не нужно сейчас, но просто интересно, если бы вы могли добавить это)

доступных на веб-странице, с использованием urllib2 и BeautifulSoup4

    import urllib2
    from bs4 import BeautifulSoup
    url = urllib2.urlopen("http://www.espncricinfo.com/").read()
    soup = BeautifulSoup(url)
    for line in soup.find_all('a'):
            print(line.get('href'))
import urllib2
import BeautifulSoup

request = urllib2.Request("http://www.gpsbasecamp.com/national-parks")
response = urllib2.urlopen(request)
soup = BeautifulSoup.BeautifulSoup(response)
for a in soup.findAll('a'):
  if 'national-park' in a['href']:
    print 'found a url with national-park in the link'
 R J15 авг. 2018 г., 19:52
Это решило проблему с моим кодом. Спасибо
import urllib2
from bs4 import BeautifulSoup
a=urllib2.urlopen('http://dir.yahoo.com')
code=a.read()
soup=BeautifulSoup(code)
links=soup.findAll("a")
#To get href part alone
print links[0].attrs['href']

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

import urllib2
import re
url = "http://www.somewhere.com"
page = urllib2.urlopen(url)
page = page.read()
links = re.findall(r"<a.*?\s*href=\"(.*?)\".*?>(.*?)</a>", page)
for link in links:
    print('href: %s, HTML text: %s' % (link[0], link[1]))
 alexis11 июн. 2016 г., 01:20
@ user1063287, в Интернете полно учебников по регулярным выражениям. Это стоит того, чтобы почитать пару. Хотя RE могут быть действительно запутанными, тот, о котором вы спрашиваете, довольно прост.
 allcaps18 мар. 2014 г., 11:08
Почему бы не использовать регулярные выражения для анализа html: / Stackoverflow.com вопросы / 1732348 / ...
 user106328706 апр. 2013 г., 06:46
Мне бы хотелось понять это, где я могу эффективно узнать, что(r"<a.*?\s*href=\"(.*?)\".*?>(.*?)</a>", page) средства? Благодарность
 Ufoguy19 янв. 2014 г., 17:35
Действительно плохая идея. Поврежденный HTML везде.

Ваш ответ на вопрос