





Для таких задач я всегда буду использовать lxml. Вы также можете использовать красивый суп.
import lxml.html
t = lxml.html.parse(url)
print t.find(".//title").text
ИЗМЕНИТЬ на основе комментария:
from urllib2 import urlopen
from lxml.html import parse
url = "https://www.google.com"
page = urlopen(url)
p = parse(page)
print p.find(".//title").text
На всякий случай вы получите IOError с кодом выше: stackoverflow.com/questions/3116269/…
Вероятно, это перебор для такой простой задачи, но если вы планируете делать больше, то разумнее начать с этих инструментов (механизация, BeautifulSoup), потому что они намного проще в использовании, чем альтернативы (urllib для получения контента и регулярное выражение или какой-то другой парсер для разбора html)
Ссылки: BeautifulSoupмеханизировать
#!/usr/bin/env python
#coding:utf-8
from bs4 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()
У объекта Mechanize Browser есть метод title (). Таким образом, код из эта почта можно переписать как:
from mechanize import Browser
br = Browser()
br.open("http://www.google.com/")
print br.title()
Вот упрощенная версия Ответ @Vinko Vrsalovic:
import urllib2
from BeautifulSoup import BeautifulSoup
soup = BeautifulSoup(urllib2.urlopen("https://www.google.com"))
print soup.title.string
ПРИМЕЧАНИЕ:
суп. название находит первый элемент заглавиекуда угодно в html-документе
title.string предполагает, что у него есть только дочерний узел один, и этот дочерний узел является нить
Для beautifulsoup 4.x используйте другой импорт:
from bs4 import BeautifulSoup
Спасибо! В случае, если кто-то столкнется с подобными проблемами, в моей среде Python3 мне пришлось использовать urlllib.request вместо urllib2. Не знаю почему. Чтобы избежать предупреждения BeautifulSoup о моем парсере, мне пришлось использовать soup = BeautifulSoup(urllib.request.urlopen(url), "lxml").
Для python 3 используйте import urllib.request as urllib вместо import urllib2
Имейте в виду, что в случае отсутствия атрибута title ИЛИ пустого заголовка, поскольку <title></title>, выполнение soup.title.string вернет None
@Eitanmg: Действительно, repl.it/@zed1/beautifulsoup-empty-title-is-none
soup.title.string фактически возвращает строку Unicode.
Чтобы преобразовать это в обычную строку, вам нужно сделать
string=string.encode('ascii','ignore')
Это просто удалит любые символы, отличные от ascii, что, вероятно, не то, что вам нужно. Если вам действительно нужны байты (что дает encode), а не строка, кодируйте правильным charset. например, string.encode('utf-8').
Используя 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 = tag == 'title'
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
Стоит отметить, что этот сценарий предназначен для Python 3. модуль HtmlParser был переименован в html.parser в Python 3.x. Аналогичным образом urllib.request был добавлен в Python 3.
Вероятно, лучше явно преобразовать байты в строку r=urlopen(url), encoding = r.info().get_content_charset() и html_string = r.read().decode(encoding).
Нет необходимости импортировать другие библиотеки. Запрос имеет встроенную функцию.
>> 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'
Часто кажется, что «импорт других библиотек» требует больше работы. Спасибо, что помогли нам этого избежать!
Использование регулярных выражений
import re
match = re.search('<title>(.*?)</title>', raw_html)
title = match.group(1) if match else 'No title'
Что на самом деле .group (1)? Любая ссылка?
Привет, group(0) вернет весь матч. Для справки см. спички.
Это пропустит любые случаи, когда теги заголовка не сформированы точно как <title> </title> (верхний регистр, смешанный регистр, интервал)
Я бы также включил <title. *?> На случай, если в теге title есть другие данные.
Вот отказоустойчивая реализация HTMLParser.
Вы можете бросить что угодно в get_title(), не сломав его, если произойдет что-нибудь неожиданное.
get_title() вернет None.
Когда Parser() загружает страницу, он кодирует ее в ASCII.
независимо от кодировки, используемой на странице, игнорируя любые ошибки.
Было бы тривиально изменить to_ascii() для преобразования данных в UTF-8 или любую другую кодировку. Просто добавьте аргумент кодировки и переименуйте функцию во что-то вроде to_encoding().
.
По умолчанию HTMLParser() ломается на сломанном html, он ломается даже на таких тривиальных вещах, как несовпадающие теги. Чтобы предотвратить такое поведение, я заменил метод ошибок HTMLParser() функцией, которая игнорирует ошибки.
#-*-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'))
Использование lxml ...
Получение его со страницы, помеченной мета-тегами в соответствии с протоколом Facebook opengraph:
import lxml.html.parse
html_doc = lxml.html.parse(some_url)
t = html_doc.xpath('//meta[@property = "og:title"]/@content')[0]
или используя .xpath с lxml:
t = html_doc.xpath(".//title")[0].text
Используйте soup.select_one для таргетинга тега заголовка
import requests
from bs4 import BeautifulSoup as bs
r = requests.get('url')
soup = bs(r.content, 'lxml')
print(soup.select_one('title').text)
В Python3 мы можем вызвать метод urlopen из urllib.request и BeautifulSoup из библиотеки bs4, чтобы получить заголовок страницы.
from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("https://www.google.com")
soup = BeautifulSoup(html, 'lxml')
print(soup.title.string)
Здесь мы используем самый эффективный парсер lxml.
С тех пор, как был задан этот вопрос, многие веб-страницы начали использовать метатег og: title, который содержит исходный заголовок, в то время как <title> часто имеет префикс и суффикс с другими данными. Первоначально использовавшийся только Facebook как часть OpenGraph, многие сайты предоставляют метаданные OpenGraph. og: title стал стандартным источником заголовка страницы, особенно новостных статей.