可以将更强大的HTML解析器连接到Python mechanize吗?

9 投票
3 回答
3591 浏览
提问于 2025-04-15 16:17

我正在尝试使用mechanize这个工具在一个网站上解析并提交一个表单,但它似乎无法识别这个表单和里面的元素。我怀疑是因为这个网站的HTML代码写得不好,导致mechanize处理不了。我想先用一个更擅长处理糟糕HTML的解析器(比如lxml或BeautifulSoup)来清理这些代码,然后再把处理好的内容交给表单解析器。因为我不仅需要mechanize来提交表单,还需要它来保持会话(我是在登录状态下操作这个表单的)。

我不太确定该怎么做,如果这确实可行的话……我对HTTP协议的各种细节不是很熟悉,不太清楚怎么把不同的部分结合在一起。有没有什么建议?

3 个回答

1

你想要的功能可以通过 lxml.etree 来实现,它是 xml.etree.ElementTree 的一个替代品,属于 lxml 库的一部分。

首先,我们来看看一些格式不太正确的 HTML:

% cat bad.html
<html>
<HEAD>
    <TITLE>this HTML is awful</title>
</head>
<body>
    <h1>THIS IS H1</H1>
    <A HREF=MYLINK.HTML>This is a link and it is awful</a>
    <img src=yay.gif>
</body>
</html>

(注意开闭标签的大小写混合,还有缺少的引号)。

然后我们对它进行解析:

>>> from lxml import etree
>>> bad = file('bad.html').read()
>>> html = etree.HTML(bad)
>>> print etree.tostring(html)
<html><head><title>this HTML is awful</title></head><body>
    <h1>THIS IS H1</h1>
    <a href="MYLINK.HTML">This is a link and it is awful</a>
    <img src="yay.gif"/></body></html>

你会发现标签和引号都被自动修正了。

如果你之前在解析 HTML 时遇到问题,这可能就是你需要的解决方案。至于 HTTP 的细节,那是另一个话题了。

10

我遇到一个问题,就是一个表单的字段缺失了。我找了半天没发现有什么错误的HTML代码,但我觉得这可能是问题的原因,所以我用了BeautifulSoup的prettify功能来解析它,结果成功了。

resp = br.open(url)
soup = BeautifulSoup(resp.get_data())
resp.set_data(soup.prettify())
br.set_response(resp)

我很想知道怎么能自动做到这一点。

编辑:我找到了自动实现的方法。

class PrettifyHandler(mechanize.BaseHandler):
    def http_response(self, request, response):
        if not hasattr(response, "seek"):
            response = mechanize.response_seek_wrapper(response)
        # only use BeautifulSoup if response is html
        if response.info().dict.has_key('content-type') and ('html' in response.info().dict['content-type']):
            soup = BeautifulSoup(response.get_data())
            response.set_data(soup.prettify())
        return response

    # also parse https in the same way
    https_response = http_response

br = mechanize.Browser()
br.add_handler(PrettifyHandler())

br现在会使用BeautifulSoup来解析所有包含HTML的响应,这些响应的内容类型(mime类型)是text/html

3

mechanize网站的第一页上,有一个很大的例子:

# Sometimes it's useful to process bad headers or bad HTML:
response = br.response()  # this is a copy of response
headers = response.info()  # currently, this is a mimetools.Message
headers["Content-type"] = "text/html; charset=utf-8"
response.set_data(response.get_data().replace("<!---", "<!--"))
br.set_response(response)

所以看起来可以用另一个解析器先处理一下响应,这样就能生成格式正确的HTML,然后再把它交给mechanize进行进一步处理。

撰写回答