¿Cómo puedo recuperar los enlaces de una página web y copiar la dirección URL de los enlaces usando Python?
141
¿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 fragmento corto usando la clase SoupStrainer en BeautifulSoup:
import httplib2
from bs4 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'])
La documentación de BeautifulSoup es bastante buena y cubre varios escenarios típicos:
https://www.crummy.com/software/BeautifulSoup/bs4/doc/
Editar: Tenga en cuenta que usé la clase SoupStrainer porque es un poco más eficiente (memoria y velocidad), si sabe de antemano lo que está analizando.
/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."
has_attr
. En cambio, veo que hay algo llamadohas_key
y funciona.Para completar, la versión BeautifulSoup 4, haciendo uso de la codificación proporcionada por el servidor también:
o la versión de Python 2:
y una versión que usa la
requests
biblioteca , que tal como está escrita funcionará tanto en Python 2 como en 3:La
soup.find_all('a', href=True)
llamada encuentra todos los<a>
elementos que tienen unhref
atributo; los elementos sin el atributo se omiten.BeautifulSoup 3 detuvo el desarrollo en marzo de 2012; los nuevos proyectos realmente deberían usar BeautifulSoup 4, siempre.
Tenga en cuenta que debe dejar la decodificación del HTML de bytes a BeautifulSoup . Puede informar a BeautifulSoup del conjunto de caracteres que se encuentra en los encabezados de respuesta HTTP para ayudar en la decodificación, pero esto puede ser incorrecto y contradictorio con una
<meta>
información de encabezado que se encuentra en el propio HTML, razón por la cual lo anterior usa el método de clase interna BeautifulSoupEncodingDetector.find_declared_encoding()
para asegurarse de que Estas sugerencias de codificación incorporadas ganan a un servidor mal configurado.Con
requests
, elresponse.encoding
atributo predeterminado es Latin-1 si la respuesta tiene un tipotext/*
MIME, incluso si no se devuelve ningún conjunto de caracteres. Esto es coherente con los RFC de HTTP, pero es doloroso cuando se usa con el análisis HTML, por lo que debe ignorar ese atributo cuando nocharset
se establece en el encabezado Content-Type.fuente
SoupStrainer
quieres decir? No fue a ninguna parte, todavía es parte del proyecto .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 ninguna razón para usar BeautifulSoup, a menos que esté en Google App Engine o algo en lo que no se permita nada que no sea Python.
lxml.html también admite selectores CSS3, por lo que este tipo de cosas es trivial.
Un ejemplo con lxml y xpath se vería así:
fuente
lxml
como el analizador predeterminado si está instalado.fuente
El siguiente código es para recuperar todos los enlaces disponibles en una página web usando
urllib2
yBeautifulSoup4
:fuente
Bajo el capó, BeautifulSoup ahora usa lxml. Solicitudes, lxml y comprensiones de listas hacen una combinación asesina
En la lista de compilación, "if '//' y 'url.com' no están en x" es un método simple para eliminar la lista de url de las URL de navegación 'internas' del sitio, etc.
fuente
solo para obtener los enlaces, sin B.soup y regex:
para operaciones más complejas, por supuesto, BSoup sigue siendo preferido.
fuente
<a
yhref
? ¿Decirrel="nofollow"
oonclick="..."
incluso una nueva línea? stackoverflow.com/questions/1732348/…Este script hace lo que buscas, pero también resuelve los enlaces relativos a enlaces absolutos.
fuente
Para encontrar todos los enlaces, en este ejemplo usaremos el módulo urllib2 junto con el re.module * Una de las funciones más poderosas en el módulo re es "re.findall ()". Mientras que re.search () se usa para encontrar la primera coincidencia de un patrón, re.findall () encuentra todas las coincidencias y las devuelve como una lista de cadenas, y cada cadena representa una coincidencia *
fuente
¿Por qué no usar expresiones regulares?
fuente
(r"<a.*?\s*href=\"(.*?)\".*?>(.*?)</a>", page)
significa? ¡Gracias!Los enlaces pueden estar dentro de una variedad de atributos para que pueda pasar una lista de esos atributos para seleccionar
por ejemplo, con el atributo src y href (aquí estoy usando el operador comienza con ^ para especificar que cualquiera de estos valores de atributos comience con http. Puede personalizar esto según sea necesario
Atributo = selectores de valor
fuente
He aquí un ejemplo usando @ars respuesta aceptada y los
BeautifulSoup4
,requests
ywget
módulos para manejar las descargas.fuente
Encontré la respuesta de @ Blairg23 funcionando, después de la siguiente corrección (cubriendo el escenario donde no funcionó correctamente):
Para Python 3:
urllib.parse.urljoin
tiene que usarse para obtener la URL completa en su lugar.fuente
El propio analizador de BeatifulSoup puede ser lento. Puede ser más factible usar lxml, que es capaz de analizar directamente desde una URL (con algunas limitaciones que se mencionan a continuación).
El código anterior devolverá los enlaces tal como están, y en la mayoría de los casos serían enlaces relativos o absolutos de la raíz del sitio. Dado que mi caso de uso era solo extraer un cierto tipo de enlaces, a continuación hay una versión que convierte los enlaces a URL completos y que opcionalmente acepta un patrón global como
*.mp3
. Sin embargo, no manejará puntos simples y dobles en las rutas relativas, pero hasta ahora no tuve la necesidad de hacerlo. Si necesita analizar fragmentos de URL que contengan../
o./
luego, urlparse.urljoin puede ser útil.NOTA : El análisis directo de URL de lxml no maneja la carga
https
y no realiza redireccionamientos, por lo que por esta razón la siguiente versión está usandourllib2
+lxml
.El uso es el siguiente:
fuente
lxml
solo puede manejar una entrada válida, ¿cómo puede reemplazarlaBeautifulSoup
?lxml.html
es un poco más indulgente que ellxml.etree
. Si su entrada no está bien formada, puede establecer explícitamente el analizador BeautifulSoup: lxml.de/elementsoup.html . Y si vas con BeatifulSoup, entonces BS3 es una mejor opción.fuente
Puede haber muchos enlaces duplicados junto con enlaces externos e internos. Para diferenciar entre los dos y simplemente obtener enlaces únicos usando conjuntos:
fuente