【问题标题】:How to speed up parsing an 10MB HTML file with BeautifulSoup如何使用 BeautifulSoup 加速解析 10MB 的 HTML 文件
【发布时间】:2015-05-23 08:18:01
【问题描述】:

我正在使用 Beautifulsoup 解析大小在 3 到 10MB 之间的大型 HTMl 文件。不幸的是,99% 的数据是我想要解析的内容。该文件实际上包含一个小标题、一些 js 脚本以及 1,000 到 10,000 个项目。每个项目由以下表格行组成:

<tr class="New" id="content_id">
    <td class="item" align="center"> 
    </td><td align="center">
         <a onclick="somecode"><img src="/images/sample.gif" alt="alttext" class="image"></a>
    </td><td style="astyle">[content1]</td><td>[content2]</td><td>[content3]</td><td>[content4]</td><td>[content5]</td><td style="bstyle">[content6]</td><td>[content7]</td><td>[content8]</td><td>[content9]</td><td>[content10]</td><td>[content11]</td><td></td><td>[content12]</td><td>[content13]</td><td>
         <a href="somejs">[content14]</a>
    </td><td>
         <a href="somejs">[content15]</a>
    </td><td>[content16]</td><td>
         <a title="" href="somejs">[content16]</a>
    </td><td>
         <a title="" href="somejs">[content17]</a>
    </td>
</tr>

注意每个 [content] 占位符都是我需要解析的相关数据。

我尝试了各种常见的优化,例如 a) 使用不同的解析器,b) 使用 SoupStrainer,c) 定义编码

b) 和 c) 在我记录所花费的时间时实际上没有任何效果。不同的解析器有很大的影响。当我在 1.5k 项目列表(相对较小的列表)上运行以下脚本时,我得到以下解析时间(我在 2012 年 Mac Book Air 上运行实验):

#1653 items parsed in 15.5 seconds with lxml
#xml takes 27 sec
#html5lib takes 69 sec
#html.parser takes 24 sec

current = datetime.datetime.utcnow()
strainer = SoupStrainer('table', attrs={'id':'contenttable'})
soup = BeautifulSoup(html,'lxml',parse_only=strainer,from_encoding="UTF-8")
print datetime.datetime.utcnow() - current

问题:除了我目前使用的以外,还有什么可以用来显着缩短解析时间的调整吗?

到目前为止,我只能考虑增加 CPU 功率。

【问题讨论】:

  • 您是一次加载整个页面吗?你是如何解析每一行的?也许您可以使用生成器一次解析一行(避免较大文档的内存问题)。
  • 我敢肯定我会为此受到抨击,因为“HTML 不是常规语言”,但如果每个“项目”都是正确的 HTML,就像你展示的那样,你可以迭代在文件的行上(抛出一对 next() 方法调用以加快不必要的检查)并使用正则表达式来提取您需要的内容。

标签: python performance parsing beautifulsoup lxml


【解决方案1】:

假设您首先将整个文件读入内存,那么您无能为力。如果 HTML 在很多地方被破坏,那么解析器必须执行更多工作来尝试猜测正确的结构。

在 Python 中解析 XML/HTML 时,根据我的经验,lxml 是最快且最节省内存的(与 xml.minidom 或 BeautifulSoup 之类的东西相比)。

但是,我在不到 15 秒的时间内解析了大于 10MB 的简单 XML 文件,因此这让我相信您可能有非常讨厌/重度嵌套的 HTML,这会阻塞解析器。无论是那个还是我的硬件都非常棒(i7 2700k 和 SSD)。

【讨论】:

    【解决方案2】:

    lxml 看起来是 Python 中最好的解决方案。

    我们在构建时对所有解析器/平台进行基准测试:serpapi.com https://medium.com/@vikoky/fastest-html-parser-available-now-f677a68b81dd

    【讨论】:

    • 我不久前得出了同样的结论。我一直不明白为什么 BS 很受欢迎。
    • @pguardiario 因为它的语法非常容易用于解析,无论网站类型如何。您还有其他建议吗,
    • 我的建议是使用lxml + css。更简单的语法和更好的性能。
    • CSS 绝对是解析 HTML 的好方法。并且可以使用 document.getElementsByClassName() 从浏览器控制台轻松测试
    【解决方案3】:

    您是否尝试过使用 lxml iterparse 并在每次迭代时删除节点。这是一个excellent article,它讨论了如何解析大文件。见最后解决方案。

    【讨论】:

    • iterparse 在您关心降低内存使用率时很好,但解析速度不会比常规的 parse() 方法快。他们都构建了同一棵树。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-04
    • 2013-03-10
    • 2020-03-19
    • 2017-10-28
    • 2022-01-12
    相关资源
    最近更新 更多