Python: 查找<title>

0 投票
3 回答
3607 浏览
提问于 2025-04-15 22:56

我有这样的代码:

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

撰写回答