Frage

Wie kann ich die Links einer Webseite abrufen und kopieren Sie die URL-Adresse der Links Python?

War es hilfreich?

Lösung

Hier ist ein kurzer Ausschnitt der SoupStrainer Klasse in BeautifulSoup mit:

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'])

Die BeautifulSoup Dokumentation ist eigentlich ganz gut, und deckt eine Reihe von typischen Szenarien:

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

Edit:. Beachten Sie, dass ich die SoupStrainer Klasse verwendet, weil es ein bisschen effizienter (Speicher und Geschwindigkeit weise) ist, wenn Sie wissen, was Sie im Voraus sind Parsen

Andere Tipps

Die Vollständigkeit halber, die BeautifulSoup 4-Version, die Verwendung der auch vom Server gelieferten Codierung machen:

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']

oder die Python 3-Version:

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'])

und eine Version mit der requests Bibliothek , die als geschrieben wird 2 und 3 in beiden Python arbeiten:

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'])

Der soup.find_all('a', href=True) Aufruf findet alle <a> Elemente, die ein href Attribut haben; Elemente ohne das Attribut ausgelassen.

BeautifulSoup 3 gestoppt Entwicklung März 2012; neue Projekte sollten wirklich nutzen BeautifulSoup 4, immer.

Beachten Sie, dass Sie verlassen sollten die HTML-Decodierung von Bytes zu BeautifulSoup . Sie können BeautifulSoup des characterset in den HTTP-Response-Header gefunden informieren bei der Decodierung zu unterstützen, aber das können falsch und widerstreit mit einem <meta> Header Informationen in der HTML fand sich, weshalb die oben die verwendet BeautifulSoup interne Klassenmethode EncodingDetector.find_declared_encoding(), um sicherzustellen, dass eine solche eingebettete Codierung Hinweise über einen falsch konfigurierten Server zu gewinnen.

Mit requests, dem Attribute response.encoding standardmäßig auf Latin-1, wenn die Antwort einen text/* MIME-Typen hat, auch wenn kein characterset zurückgegeben wurde. Dies steht im Einklang mit dem HTTP-RFCs, aber schmerzhaft, wenn sie mit HTML-Analyse verwendet, so sollten Sie dieses Attribut ignorieren, wenn kein charset in den Content-Type-Header festgelegt ist.

Andere haben BeautifulSoup empfohlen, aber es ist viel besser zu nutzen lxml . Trotz seines Namens ist es auch für das Parsen und HTML Schaben. Es ist viel, viel schneller als BeautifulSoup, und es Griffe sogar „gebrochen“ HTML besser als BeautifulSoup (ihren Anspruch auf Ruhm). Es hat eine Kompatibilität API für BeautifulSoup auch, wenn Sie nicht die lxml API lernen wollen.

Ian Blicking stimmt .

Es gibt keinen Grund BeautifulSoup mehr zu verwenden, es sei denn, Sie sind auf Google App Engine oder etwas, wo etwas nicht rein Python ist nicht erlaubt.

lxml.html unterstützt auch CSS3-Selektoren so diese Art der Sache trivial ist.

Ein Beispiel mit lxml und XPath würde wie folgt aussehen:

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
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'

Der folgende Code ist auf alle Links in einer Webseite verfügbar abrufen urllib2 und BeautifulSoup4 mit:

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'))

Unter der Haube verwendet BeautifulSoup jetzt lxml. Anfragen, lxml & Listenkomprehensionen macht eine Killer-Combo.

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]

In der Liste comp, die "if '//' und 'url.com' nicht in x" ist eine einfache Methode, um die URL-Liste der Sites 'internen' Navigation Urls schrubben, etc.

Um alle Links zu finden, die wir in diesem Beispiel wird die urllib2 Modul verwenden zusammen mit der re.module * Einer der mächtigsten Funktion im Modul re ist „re.findall ()“. Während re.search () verwendet wird, um das erste Spiel für ein Muster zu finden, re.findall () findet alle die Spiele und gibt sie als eine Liste von Zeichenketten, wobei jede Zeichenfolge, die ein Spiel *

import urllib2

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

nur für die Links bekommen, ohne B.soup und regex:

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]

für komplexere Operationen, natürlich ist BSoup noch bevorzugt.

Warum keine regulären Ausdrücke:

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]))

Dieses Skript tut, was Sie suchen, aber löst auch die relativen Links zu absoluten Links.

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

Links können in einer Vielzahl von Attributen, so dass Sie eine Liste der Attribute übergeben könnten, um

zum Beispiel mit src und href-Attribut (hier verwende ich die Starts mit ^ Operator angeben, dass eine dieser Attribute Werte mit http beginnt. Sie können zuzuschneiden dies als erforderlich

from bs4 import BeautifulSoup as bs
import requests
r = requests.get('https://stackoverflow.com/')
soup = bs(r.content, 'lxml')
links = [item['href'] if item.get('href') is not None else item['src'] for item in soup.select('[href^="http"], [src^="http"]') ]
print(links)

Attribut = Wert Selektoren

  

[attr ^ = Wert]

     

steht für Elemente mit einem Attributnamen von attr dessen Wert des Präfix (voran) nach Wert.

Hier ist ein Beispiel @ars akzeptierte Antwort und den BeautifulSoup4, requests und wget Module mit den Downloads zu handhaben.

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)

fand ich die Antwort von @ Blairg23 arbeitet, nach der folgenden Korrektur (für das Szenario, in dem es konnte nicht richtig funktionieren):

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)

Für Python 3:

urllib.parse.urljoin verwendet werden muss, um stattdessen die vollständige URL zu erhalten.

BeatifulSoup eigenen Parser kann langsam sein. Es könnte möglich sein, zu verwenden lxml , die von einer URL Parsing direkt fähig ist ( mit einigen Einschränkungen weiter unten erwähnt).

import lxml.html

doc = lxml.html.parse(url)

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

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

Der obige Code wird die Links zurück, wie ist, und in den meisten Fällen würden sie relative Links oder absolut von der Website root sein. Da mein Anwendungsfall nur war es, eine bestimmte Art von Links zu extrahieren, ist eine Version, die die Links zu dem vollständigen URLs umwandelt und die akzeptiert optional ein glob Muster wie *.mp3. Es wird allerdings nicht Einzel- und Doppelpunkte in den relativen Pfaden handhaben, aber bisher habe ich nicht die Notwendigkeit dafür. Wenn Sie dann enthält ../ oder ./ URL-Fragmente analysieren müssen urlparse.urljoin könnte kommt in praktisch.

Hinweis :. Direkt lxml URL-Analyse behandelt nicht aus https Laden und Umleitungen nicht tun, so aus diesem Grunde unter der Version urllib2 + lxml mit

#!/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

Die Nutzung ist wie folgt:

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"
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']
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top