2008-09-09 25 views

Respuesta

49

Siempre usaré lxml para tales tareas. También puede usar .

import lxml.html 
t = lxml.html.parse(url) 
print t.find(".//title").text 
+4

Sólo en caso de que se IOError con el código anterior: http: //stackoverflow.com/questions/3116269/error-with-parse-function-in-lxml – Yosh

+0

[lxml puede tener problemas con Unicode] (http://stackoverflow.com/q/15302125/4279), podría [usar bs4.UnicodeDammit para ayudarlo a encontrar la codificación de caracteres correcta] (http://stackoverflow.com/a/15305248/4279) – jfs

7

Esta es probablemente una exageración para una tarea tan sencilla, pero si va a hacer más que eso, entonces es más sano que partir de estas herramientas (mecanizar, BeautifulSoup), ya que son mucho más fáciles de usar que las alternativas (urllib para obtener contenido y regexen o algún otro analizador para analizar hTML)

Enlaces: BeautifulSoup mechanize

#!/usr/bin/env python 
#coding:utf-8 

from BeautifulSoup import BeautifulSoup 
from mechanize import Browser 

#This retrieves the webpage content 
br = Browser() 
res = br.open("https://www.google.com/") 
data = res.get_data() 

#This parses the content 
soup = BeautifulSoup(data) 
title = soup.find('title') 

#This outputs the content :) 
print title.renderContents() 
11

El objeto mecanizar navegador tiene un título() método. Así que el código de this post se puede reescribir como:

from mechanize import Browser 
br = Browser() 
br.open("http://www.google.com/") 
print br.title() 
64

Aquí hay una versión simplificada de @Vinko Vrsalovic's answer:

import urllib2 
from BeautifulSoup import BeautifulSoup 

soup = BeautifulSoup(urllib2.urlopen("https://www.google.com")) 
print soup.title.string 

NOTA:

  • soup.title busca el primer título elemento en cualquier parte en el documento html

  • title.string asume que sólo tiene un nodo niño, y ese nodo hijo es una cadena

Para beautifulsoup 4.x, uso distinto de importación:

from bs4 import BeautifulSoup 
+4

¡Gracias! En caso de que alguien se encuentre con problemas similares, en mi entorno Python3, tuve que usar 'urlllib.request' en lugar de' urllib2'. No estoy seguro por qué. Para evitar la advertencia de BeautifulSoup sobre mi analizador sintáctico, tuve que hacer 'soup = BeautifulSoup (urllib.request.urlopen (url)," lxml ")'. – sudo

0

soup.title.string en realidad devuelve una cadena Unicode. Para convertir eso en la cadena normal, lo que necesita hacer string=string.encode('ascii','ignore')

+0

Eso eliminará cualquier caracter no ascii que probablemente no es lo que quieres. Si realmente quieres bytes (lo que 'codde' da) y no una cadena, codifica con el' charset' correcto. por ejemplo, 'string.encode ('utf-8')'. – reubano

4

Usando HTMLParser:

from urllib.request import urlopen 
from html.parser import HTMLParser 


class TitleParser(HTMLParser): 
    def __init__(self): 
     HTMLParser.__init__(self) 
     self.match = False 
     self.title = '' 

    def handle_starttag(self, tag, attributes): 
     self.match = True if tag == 'title' else False 

    def handle_data(self, data): 
     if self.match: 
      self.title = data 
      self.match = False 

url = "http://example.com/" 
html_string = str(urlopen(url).read()) 

parser = TitleParser() 
parser.feed(html_string) 
print(parser.title) # prints: Example Domain 
+0

Vale la pena observar que este script es para Python 3. El módulo HtmlParser se renombró a html.parser en Python 3.x. De manera similar, se agregó urllib.request en Python 3. – satishgoda

+1

Probablemente sea mejor convertir explícitamente los bytes en una cadena, 'r = urlopen (url)', 'encoding = r.info(). Get_content_charset()', y 'html_string = r.read(). decode (codificación) '. – reubano

3

No hay necesidad de importar otras bibliotecas. La solicitud tiene esta funcionalidad incorporada.

>> hearders = {'headers':'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:51.0) Gecko/20100101 Firefox/51.0'} 
>>> n = requests.get('http://www.imdb.com/title/tt0108778/', headers=hearders) 
>>> al = n.text 
>>> al[al.find('<title>') + 7 : al.find('</title>')] 
u'Friends (TV Series 1994\u20132004) - IMDb' 
1

el uso de expresiones regulares

import re 
match = re.search('<title>(.*?)</title>', raw_html) 
title = match.group(1) if match else 'No title' 
+0

¿Qué es realmente .grupo (1)? ¿Alguna referencia? – pije

+0

Hola, 'group (0)' devolvería la coincidencia completa. Ver [match-objects] (https://docs.python.org/3.6/library/re.html#match-objects) para referencia. – Finn

+0

Esto extrañará los casos en que las etiquetas de título no estén formadas exactamente como (mayúsculas, minúsculas, espacios) –

0

Aquí hay una tolerancia a fallos HTMLParser aplicación.
Puede lanzar casi cualquier cosa al get_title() sin que se rompa, si ocurre algo inesperado get_title() devolverá None.
Cuando Parser() descarga la página a ASCII independientemente del juego de caracteres utilizado en la página ignorando los errores. Sería trivial cambiar to_ascii() para convertir los datos en UTF-8 o cualquier otra codificación. Simplemente agregue un argumento de codificación y cambie el nombre de la función a algo como to_encoding().
Por defecto HTMLParser() se romperá en html roto, incluso se romperá en cosas triviales como etiquetas que no coinciden. Para evitar este comportamiento, reemplacé el método de error HTMLParser() con una función que ignorará los errores.

#-*-coding:utf8;-*- 
#qpy:3 
#qpy:console 

''' 
Extract the title from a web page using 
the standard lib. 
''' 

from html.parser import HTMLParser 
from urllib.request import urlopen 
import urllib 

def error_callback(*_, **__): 
    pass 

def is_string(data): 
    return isinstance(data, str) 

def is_bytes(data): 
    return isinstance(data, bytes) 

def to_ascii(data): 
    if is_string(data): 
     data = data.encode('ascii', errors='ignore') 
    elif is_bytes(data): 
     data = data.decode('ascii', errors='ignore') 
    else: 
     data = str(data).encode('ascii', errors='ignore') 
    return data 


class Parser(HTMLParser): 
    def __init__(self, url): 
     self.title = None 
     self.rec = False 
     HTMLParser.__init__(self) 
     try: 
      self.feed(to_ascii(urlopen(url).read())) 
     except urllib.error.HTTPError: 
      return 
     except urllib.error.URLError: 
      return 
     except ValueError: 
      return 

     self.rec = False 
     self.error = error_callback 

    def handle_starttag(self, tag, attrs): 
     if tag == 'title': 
      self.rec = True 

    def handle_data(self, data): 
     if self.rec: 
      self.title = data 

    def handle_endtag(self, tag): 
     if tag == 'title': 
      self.rec = False 


def get_title(url): 
    return Parser(url).title 

print(get_title('http://www.google.com')) 
Cuestiones relacionadas