usar una tutorial script scraping pagina medium extraer datos como python hyperlink beautifulsoup

una - recuperar enlaces desde la página web usando Python y BeautifulSoup



web scraping python beautifulsoup tutorial (14)

¿Por qué no usar expresiones regulares?

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

¿Cómo puedo recuperar los enlaces de una página web y copiar la dirección URL de los enlaces usando Python?


Aquí hay un ejemplo que usa la respuesta aceptada de @ars y los módulos BeautifulSoup4 , requests y wget para manejar las descargas.

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)


Aquí hay un fragmento corto usando la clase SoupStrainer en BeautifulSoup:

import httplib2 from BeautifulSoup import BeautifulSoup, SoupStrainer http = httplib2.Http() status, response = http.request(''http://www.nytimes.com'') for link in BeautifulSoup(response, parseOnlyThese=SoupStrainer(''a'')): if link.has_attr(''href''): print link[''href'']

La documentación de BeautifulSoup en realidad es bastante buena y cubre varios escenarios típicos:

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

Editar: Tenga en cuenta que utilicé la clase SoupStrainer porque es un poco más eficiente (memoria y velocidad), si sabe lo que está analizando de antemano.


Bajo el capó, BeautifulSoup ahora usa lxml. Solicitudes, lxml y listas de comprensión hacen un combo asesino.

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]

En el comp de la lista, "if ''//'' y ''url.com'' no en x" es un método simple para borrar la lista de direcciones URL internas de navegación de los sitios, etc.


El analizador propio de BeatifulSoup puede ser lento. Podría ser más factible usar lxml que es capaz de analizar directamente desde una URL (con algunas limitaciones que se mencionan a continuación).

import lxml.html doc = lxml.html.parse(url) links = doc.xpath(''//a[@href]'') for link in links: print link.attrib[''href'']

El código anterior devolverá los enlaces como están, y en la mayoría de los casos serán enlaces relativos o absolutos desde la raíz del sitio. Como mi caso de uso consistía en extraer solo un cierto tipo de enlaces, a continuación se muestra una versión que convierte los enlaces a URL completas y que opcionalmente acepta un patrón global como *.mp3 . Sin embargo, no manejará puntos individuales y dobles en las rutas relativas, pero hasta ahora no tenía la necesidad de hacerlo. Si necesita analizar fragmentos de URL que contengan ../ o ./ entonces urlparse.urljoin podría ser útil.

NOTA : El análisis directo de lxml url no maneja la carga desde https y no hace redirecciones, por lo que la siguiente versión usa 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

El uso es el siguiente:

getlinks.py http://.com/a/37758066/191246 getlinks.py http://.com/a/37758066/191246 "*users*" getlinks.py http://fakedomain.mu/somepage.html "*.mp3"


El siguiente código es para recuperar todos los enlaces disponibles en una página web usando urllib2 y 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''))


Encontré la respuesta de @ Blairg23 en funcionamiento, después de la siguiente corrección (que cubre el escenario donde no funcionó correctamente):

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)

Para Python 3:

urllib.parse.urljoin tiene que ser utilizado para obtener la URL completa en su lugar.


Este script hace lo que usted busca, pero también resuelve los enlaces relativos a los enlaces absolutos.

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


Otros han recomendado BeautifulSoup, pero es mucho mejor usar lxml . A pesar de su nombre, también es para analizar y raspar HTML. Es mucho, mucho más rápido que BeautifulSoup, e incluso maneja HTML "roto" mejor que BeautifulSoup (su reclamo de fama). También tiene una API de compatibilidad para BeautifulSoup si no desea aprender la API lxml.

Ian Blicking está de acuerdo .

Ya no hay motivo para usar BeautifulSoup, a menos que esté en Google App Engine o algo en el que no se permita nada que no sea puramente Python.

lxml.html también es compatible con los selectores de CSS3 por lo que este tipo de cosas es trivial.

Un ejemplo con lxml y xpath se vería así:

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


Para completar, la versión BeautifulSoup 4, haciendo uso de la codificación proporcionada por el servidor también:

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

o la versión de 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''])

y una versión que usa la biblioteca de requests , que, como está escrito, funcionará en Python 2 y 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''])

La soup.find_all(''a'', href=True) encuentra todos los elementos <a> que tienen un atributo href ; los elementos sin el atributo se omiten.

BeautifulSoup 3 detuvo el desarrollo en marzo de 2012; nuevos proyectos realmente deberían usar BeautifulSoup 4, siempre.

Tenga en cuenta que debe dejar de decodificar el HTML de bytes a BeautifulSoup . Puede informar a BeautifulSoup del juego de caracteres encontrado en los encabezados de respuesta HTTP para ayudar en la decodificación, pero puede ser incorrecto y conflictivo con una información de encabezado <meta> encontrada en el HTML mismo, por lo que lo anterior usa el método de clase interna BeautifulSoup EncodingDetector.find_declared_encoding() para asegurarse de que dichas sugerencias de codificación incrustadas ganen sobre un servidor mal configurado.

Con las requests , el atributo response.encoding predeterminada en Latin-1 si la respuesta tiene un tipo de text/* mimetype, incluso si no se devolvió ningún conjunto de caracteres. Esto es coherente con los RFC de HTTP, pero es doloroso cuando se utiliza con el análisis de HTML, por lo que debe ignorar ese atributo cuando no se establece un juego de charset en el encabezado de tipo de contenido.


solo para obtener los enlaces, sin B.soup y 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]

para operaciones más complejas, por supuesto, aún se prefiere BSoup.


Para encontrar todos los enlaces, en este ejemplo utilizaremos el módulo urllib2 junto con el re.module * Una de las funciones más potentes del módulo re es "re.findall ()". Mientras que re.search () se usa para encontrar la primera coincidencia para un patrón, re.findall () encuentra todas las coincidencias y las devuelve como una lista de cadenas, con cada cadena representando una coincidencia *

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


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