大HTML的流解析

Enc*_*ner 5 html python parsing lxml python-requests

我在某些服务器上有一个巨大的 HTML 文件(数十兆字节),我需要定期下载和解析该文件,检测更改。因此,我尝试使用最常用的工具来完成此任务 - requestslxml

我发现的流解析的常见方法与此类似:

def fast_iter(url):
    resp = requests.get(
        url,
        stream=True
    )
    context = etree.iterparse(resp.raw, html=True)
    for event, elem in context:
        print(elem)
        if event == 'end' and elem.tag in TAGS:
            yield elem
        elem.clear()
        while elem.getprevious() is not None:
            if elem.getparent():
                del elem.getparent()[0]
            else:
                break
    del context
Run Code Online (Sandbox Code Playgroud)

但在我的例子中,它不起作用,因为iterparse()变得疯狂并返回一些从未出现在源 HTML 文件中的元素(并且它没有损坏!):

<Element vqoe at 0x7eff9762b448>
<Element jzu at 0x7eff9762b408>
<Element vvu at 0x7eff9762b3c8>
<Element d at 0x7eff9762b388>
<Element s at 0x7eff9762b348>
<Element ss_lt at 0x7eff9762b308>
Run Code Online (Sandbox Code Playgroud)

有趣的是,当我只是在本地保存这个文件并从 FS 解析 ir 时 - 一切顺利,但我真的想避免这个无用的步骤。requests返回的类文件对象有什么不同吗?这种方法有什么问题呢?

请求==2.9.1

lxml==3.5.0

Jos*_*e G 0

您需要明确要求解码:

def fast_iter(url):
    response = requests.post(url, stream=True)
    response.raw.decode_content = True
    context = etree.iterparse(response.raw, html=True, events={"end"})
    for event, elem in context:
        if event == 'end':
            yield elem
            
Run Code Online (Sandbox Code Playgroud)