Python: 查找<title>
我有这样的代码:
response = urllib2.urlopen(url)
html = response.read()
begin = html.find('<title>')
end = html.find('</title>',begin)
title = html[begin+len('<title>'):end].strip()
如果网址是 http://www.google.com,那么标题就没问题,显示为“Google”。
但是如果网址是 "http://www.britishcouncil.org/learning-english-gateway",那么标题就变成了
"<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<base href="http://www.britishcouncil.org/" />
<META http-equiv="Content-Type" Content="text/html;charset=utf-8">
<meta name="WT.sp" content="Learning;Home Page Smart View" />
<meta name="WT.cg_n" content="Learn English Gateway" />
<META NAME="DCS.dcsuri" CONTENT="/learning-english-gateway.htm">..."
到底发生了什么,为什么我不能返回“标题”?
3 个回答
0
这是一个使用Python 3的lxml和urllib库的有效解决方案。
import lxml.etree, urllib.request
def documenttitle(url):
conn = urllib.request.urlopen(url)
parser = lxml.etree.HTMLParser(encoding = "utf-8")
tree = lxml.etree.parse(conn, parser = parser)
return tree.find('.//title')
2
让我们来分析一下为什么会得到这个答案。如果你打开网站并查看源代码,你会发现里面没有 <title>...</title>
。而是有 <TITLE>...</TITLE>
。那么这两个查找操作会发生什么呢?它们的结果都是 -1
!
begin = html.find('<title>') # Result: -1
end = html.find('</title>') # Result: -1
接下来,begin+len('<title>')
的计算结果就是 -1 + 7 = 6。所以你最终得到的结果是提取 html[6:-1]
。实际上,在 Python 中,负数索引是有意义的(这是有原因的)。它表示从后往前数。因此这里的 -1 指的是 html
的最后一个字符。所以你得到的是从第6个字符(包括这个字符)到最后一个字符(不包括这个字符)的子字符串。
那我们该怎么办呢?首先,你可以使用不区分大小写的正则表达式匹配器,或者使用一个合适的 HTML 解析器。如果这只是一次性的操作,并且空间或性能不是大问题,最快的方法可能是创建一个 html
的副本,并将整个字符串转换为小写:
def get_title(html):
html_lowered = html.lower();
begin = html_lowered.find('<title>')
end = html_lowered.find('</title>')
if begin == -1 or end == -1:
return None
else:
# Find in the original html
return html[begin+len('<title>'):end].strip()
7
那个网址会返回一个包含 <TITLE>...</TITLE>
的文档,而 find
是区分大小写的。我强烈建议你使用一个HTML解析器,比如 Beautiful Soup。