【问题标题】:Replace BeautifulSoup with another (standard) HTML parsing module in this Python script用这个 Python 脚本中的另一个(标准)HTML 解析模块替换 BeautifulSoup
【发布时间】:2011-09-02 18:20:32
【问题描述】:

我用 BeautifulSoup 制作了一个脚本,它运行良好且可读性很强,但我想有一天重新分发它,而 BeautifulSoup 是我想避免的外部依赖,特别是考虑到 Windows 的使用。

这是代码,它从给定的谷歌地图用户那里获取每个用户地图链接。 ####### 标记的行是使用 BeautifulSoup 的行:

# coding: utf-8

import urllib, re
from BeautifulSoup import BeautifulSoup as bs

uid = '200931058040775970557'
start = 0
shown = 1

while True:
    url = 'http://maps.google.com/maps/user?uid='+uid+'&ptab=2&start='+str(start)
    source = urllib.urlopen(url).read()
    soup = bs(source)  ####
    maptables = soup.findAll(id=re.compile('^map[0-9]+$'))  #################
    for table in maptables:
        for line in table.findAll('a', 'maptitle'):  ################
            mapid = re.search(uid+'\.([^"]*)', str(line)).group(1)
            mapname = re.search('>(.*)</a>', str(line)).group(1).strip()[:-3]
            print shown, mapid, '\t', mapname
            shown += 1

            urllib.urlretrieve('http://maps.google.com.br/maps/ms?msid=' + uid + '.' + str(mapid) +
                               '&msa=0&output=kml', mapname + '.kml')


    if '<span>Next</span>' in str(source):
        start += 5
    else:
        break

如您所见,使用 BSoup 的代码只有三行,但我不是程序员,尝试使用其他标准的 HTML 和 XML 解析工具时遇到了很多困难,可能是因为我尝试了错误的方法,我猜。

编辑:这个问题更多的是关于替换这个脚本的三行代码,而不是找到解决可能存在的通用 html 解析问题的方法。

任何帮助将不胜感激,感谢阅读!

【问题讨论】:

  • 对于任何对代码本身感兴趣的人(从谷歌地图用户下载地图),我有一个具体的问题:stackoverflow.com/questions/7235639
  • 如果不添加依赖项,您将无法获得 真正 好的 HTML 解析器。 BeautifulSoup 的存在是有原因的。对 Python 代码的依赖并没有那么不好,它不像用户需要一个 C 编译器。另外,easy_install 也可以在 Windows 上轻松使用。
  • 也许我没有说清楚,我只是在寻找一种不使用非标准模块来执行代码中标记的操作的方法,而不是一种替换模块本身以进行通用解析操作的方法。
  • @heltonbiker,这段代码执行的逻辑需要解析HTML。
  • 请注意,谷歌地图确实有用于检索数据的 API,这可能比对适用的肉类友好页面进行屏幕截图更容易(或更允许)。 code.google.com/apis/maps/index.html

标签: python html-parsing beautifulsoup


【解决方案1】:

不幸的是,Python 在标准库中没有有用的 HTML 解析,因此解析 HTML 的唯一合理方法是使用第三方模块,如 lxml.htmlBeautifulSoup。这并不意味着您必须有一个单独的依赖项——这些模块是免费软件,如果您不想要外部依赖项,欢迎您将它们与您的代码捆绑在一起,这样就不会再使它们成为依赖比你自己写的代码。

【讨论】:

  • 这是一个供个人简单使用的单文件脚本。我的意思是“重新分发”是通过电子邮件将其发送给一些朋友:o)
  • @heltonbiker,它的简单性和有限的范围并不妨碍以一种有效的方式对其进行编程。 :).
  • @Mike Graham,用户有一个程序可以做他想做的事:它可以工作。他只需要替换其中的几行即可。
  • 我现在会接受答案,即使我的问题没有解决。
【解决方案2】:

解析 HTML 代码我看到有三种解决方案:

  • 使用简单的字符串搜索 (.find(),...) 快!
  • 使用正则表达式(又名正则表达式)
  • 使用 HTMLParser

【讨论】:

  • 这不是一个好建议。使用str.find 非常脆弱,并且在语义上无法识别 HTML,并且在大多数情况下没有用处。正则表达式从根本上无法解析 HTML;这是一个众所周知的理论和实践问题。不幸的是,stdlib HTMLParser 很脆弱且无法使用。
  • 我已经在我的脚本中使用了正则表达式,并且 HTMLParser 引发了“格式错误的文档”错误...
  • 这有帮助吗?它搜索页面中的所有链接。 import re links_regexp = re.compile('',re.IGNORECASE) html = open('toto.html','rb').read() 打印 links_regexp。 findall(html)
  • @Louis:不多,我正在寻找 html 树中的一些特定链接,如带有##### 标记的代码所示。
  • 这些选项是在标准库中执行此操作的有效方法,它们可能很差,但这是我们想要的。反对票似乎不公平。
【解决方案3】:

我已经尝试过这段代码(见下文),它显示了一个链接列表。由于我没有安装漂亮的汤并且不想安装,因此我很难根据您的代码给出的结果来检查结果。 没有任何“汤”的“纯”python代码甚至更短、更易读。 不管怎样,就在这里。告诉我你的想法 !友好的,路易斯。

#coding: utf-8

import urllib, re

uid = '200931058040775970557'
start = 0
shown = 1

while True:
    url = 'http://maps.google.com/maps/user?uid='+uid+'&ptab=2&start='+str(start)
    source = urllib.urlopen(url).read()
    while True:
        endit = source.find('maptitle')
        mapid = re.search(uid+'\.([^"]*)', str(source)).group(1)
        mapname = re.search('>(.*)</a>', str(source)).group(1).strip()[:-3]
        print shown, mapid, '\t', mapname
        shown += 1
        urllib.urlretrieve('http://maps.google.com.br/maps/ms?msid=' + uid + '.' + str(mapid) + '&msa=0&output=kml', mapname + '.kml')

    if '<span>Next</span>' in str(source):
        start += 5
    else:
        break

【讨论】:

  • 不幸的是它对我不起作用,因为它会永远循环,并且在每个循环中打印(可能不止一次)很多源代码......:o(
  • 对不起,我真的需要看看你得到的输出才能走得更远。
  • @heltonbiker : 你能把你的输出发布到某个地方,或者把它发送到某个垃圾邮箱吗?
  • 我把有趣的部分放在这里:pastebin.com/Qh2HWG1c。顺便说一句,我明白你在做什么,它不是很解析,它更像是正则表达式搜索,根本不捕获 HTML 的结构...... :o(
  • 确实,它没有捕获 HTML 结构,但我认为您正在搜索问题中所说的“用户地图链接”列表?
猜你喜欢
  • 2015-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多