2008-09-09 6 views

Répondre

49

Je vais toujours utiliser lxml pour de telles tâches. Vous pouvez également utiliser .

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

Juste au cas où vous IOError avec le code ci-dessus: http: //stackoverflow.com/questions/3116269/error-with-parse-function-in-lxml – Yosh

+0

[lxml peut avoir des problèmes avec Unicode] (http://stackoverflow.com/q/15302125/4279), vous pourriez [utiliser bs4.UnicodeDammit pour l'aider à trouver l'encodage de caractères correct] (http://stackoverflow.com/a/15305248/4279) – jfs

7

Ceci est probablement trop pour une telle tâche simple, mais si vous envisagez de faire plus que cela, il est plus raisonnable de partir de ces outils (mécaniser, BeautifulSoup) parce qu'ils sont beaucoup plus faciles à utiliser que les solutions de rechange (urllib pour obtenir du contenu et regexen ou un autre analyseur pour analyser html)

Liens: 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

L'objet du navigateur de mécaniser a un titre() méthode. Ainsi, le code de this post peut être réécrite comme:

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

Voici une version simplifiée de @Vinko Vrsalovic's answer:

import urllib2 
from BeautifulSoup import BeautifulSoup 

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

REMARQUE:

  • soup.title trouve le premier titre élément n'importe où dans le document html

  • title.string suppose qu'il n'a que un nœud enfant, et ce nœud enfant est une chaîne

Pour beautifulsoup 4.x, utilisez différents import:

from bs4 import BeautifulSoup 
+4

Merci! Au cas où quelqu'un rencontrerait des problèmes similaires, dans mon environnement Python3, j'ai dû utiliser 'urlllib.request' au lieu de' urllib2'. Pas certain de pourquoi. Pour éviter l'avertissement BeautifulSoup à propos de mon analyseur, j'ai dû faire 'soup = BeautifulSoup (urllib.request.urlopen (url)," lxml ")'. – sudo

0

soup.title.string renvoie effectivement une chaîne unicode. Pour convertir en chaîne normale, vous devez faire string=string.encode('ascii','ignore')

+0

Cela supprimera tout caractère non-ascii qui n'est probablement pas ce que vous voulez. Si vous voulez vraiment des octets (ce que 'encoder' donne) et pas une chaîne, encoder avec le bon' charset'. par exemple, 'string.encode ('utf-8')'. – reubano

4

En utilisant 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

Il serait intéressant de noter que ce script est pour Python 3. le module HtmlParser a été renommé en html.parser dans Python 3.x. De même urllib.request a été ajouté en Python 3. – satishgoda

+1

Il est probablement préférable de convertir explicitement les octets en une chaîne, 'r = urlopen (url)', 'encoding = r.info(). Get_content_charset()', et 'html_string = r.read(). decode (encodage) '. – reubano

3

Pas besoin d'importer d'autres bibliothèques. La requête a cette fonctionnalité intégrée.

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

utilisant des expressions régulières

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

Qu'est-ce que .group (1)? Toute référence? – pije

+0

Salut, 'group (0)' retournerait le match entier. Voir [match-objects] (https://docs.python.org/3.6/library/re.html#match-objects) pour référence. – Finn

+0

Cela manquera tous les cas où les étiquettes de titre ne sont pas formées exactement comme (majuscules, mixte, espacement) –

0

Voici une implémentation à tolérance de panne HTMLParser.
Vous pouvez jeter à peu près n'importe quoi à get_title() sans rupture, Si quelque chose d'inattendu se produit get_title() renverra None.
Lorsque Parser() télécharge la page, il le code à ASCII quel que soit le jeu de caractères utilisé dans la page en ignorant les erreurs. Il serait trivial de changer to_ascii() pour convertir les données en UTF-8 ou tout autre encodage. Ajoutez simplement un argument de codage et renommez la fonction en quelque chose comme to_encoding().
Par défaut, HTMLParser() va casser sur le html cassé, il va même casser sur des choses triviales comme les balises incompatibles. Pour éviter ce comportement, j'ai remplacé la méthode d'erreur HTMLParser() par une fonction qui ignore les erreurs.

#-*-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')) 
Questions connexes