【问题标题】:regex pattern in python for parsing HTML title tagspython中用于解析HTML标题标签的正则表达式模式
【发布时间】:2013-12-01 11:52:58
【问题描述】:

我正在学习在 python 中同时使用re 模块和urllib 模块,并尝试编写一个简单的网络爬虫。这是我编写的仅用于抓取网站标题的代码:

#!/usr/bin/python

import urllib
import re

urls=["http://google.com","https://facebook.com","http://reddit.com"]

i=0

these_regex="<title>(.+?)</title>"
pattern=re.compile(these_regex)

while(i<len(urls)):
        htmlfile=urllib.urlopen(urls[i])
        htmltext=htmlfile.read()
        titles=re.findall(pattern,htmltext)
        print titles
        i+=1

这为 Google 和 Reddit 提供了正确的输出,但为 Facebook 提供了正确的输出 - 就像这样:

['Google']
[]
['reddit: the front page of the internet']

这是因为,我发现在 Facebook 的页面上,title 标签如下:&lt;title id="pageTitle"&gt;。为了适应额外的id=,我将these_regex 变量修改如下:these_regex="&lt;title.+?&gt;(.+?)&lt;/title&gt;"。但这给出了以下输出:

[]
['Welcome to Facebook \xe2\x80\x94 Log in, sign up or learn more']
[]

如何将两者结合起来,以便考虑在title 标记中传递的任何其他参数?

【问题讨论】:

标签: python html regex web-scraping


【解决方案1】:

建议您使用Beautiful Soup 或任何其他解析器来解析 HTML,但如果您非常想要正则表达式,下面的代码可以完成这项工作。

正则表达式代码:

<title.*?>(.+?)</title>

工作原理:

生产:

['Google']
['Welcome to Facebook - Log In, Sign Up or Learn More']
['reddit: the front page of the internet']

【讨论】:

  • e 上的问号也使&lt;titl&gt;Google&lt;/title&gt; 匹配。你可能想摆脱它。
  • @MartijnPieters 感谢您指出这一点,尽管我认为您在整个编程生涯中都不会遇到&lt;titl&gt;Google&lt;/title&gt;,但我会解决它
  • 您会惊讶于某些 HTML 是多么草率。更重要的是问号在那里没有用。
  • 为什么\s?在这里; .*? 已经与空格匹配。如果您希望空格是明确的,为什么不使用\b 来匹配边界(在e&gt;e 和空格之间),或者使用非捕获可选组&lt;title(?:\s.+?)?&gt;
  • 您从哪里获得了如此出色的“工作原理”可视化?
【解决方案2】:

您正在使用正则表达式,而将 HTML 与此类表达式匹配变得太复杂、太快了。

改为使用 HTML 解析器,Python 有几个可供选择。我推荐你使用BeautifulSoup,一个流行的第三方库。

美汤示例:

from bs4 import BeautifulSoup

response = urllib2.urlopen(url)
soup = BeautifulSoup(response.read(), from_encoding=response.info().getparam('charset'))
title = soup.find('title').text

由于title 标签本身不包含其他标签,您可以在此处使用正则表达式,但是一旦您尝试解析嵌套标签,您遇到巨大的麻烦复杂的问题。

您的具体问题可以通过匹配title 标记中的其他字符来解决,可选:

r'<title[^>]*>([^<]+)</title>'

这匹配0个或多个不是结束&gt;括号的字符。此处的“0 或更多”允许您匹配额外属性和普通的&lt;title&gt; 标记。

【讨论】:

    【解决方案3】:

    如果你想识别所有的htlm标签,你可以使用这个

    batRegex = re.compile(r'(<[a-z]*>)')
    m1=batRegex.search(html)
    print batRegex.findall(yourstring)
    

    【讨论】:

    • 带有属性的标签呢?以上不适用于&lt;a class='link'&gt;url&lt;/a&gt;
    【解决方案4】:

    你可以用几行 gazpacho 刮出一堆标题:

    from gazpacho import Soup
    
    urls = ["http://google.com", "https://facebook.com", "http://reddit.com"]
    
    titles = []
    for url in urls:
        soup = Soup.get(url)
        title = soup.find("title", mode="first").text
        titles.append(title)
    

    这将输出:

    titles
    ['Google',
     'Facebook - Log In or Sign Up',
     'reddit: the front page of the internet']
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-22
      • 2019-01-18
      • 1970-01-01
      相关资源
      最近更新 更多