通过命令行替换HTML选择

时间:2013-04-25 13:09:25

标签: python ruby bash shell unix

编辑:我知道怎么做。我不是在寻找解决方案,我正在寻找一个流程或现有的程序建议,然后我花时间用一些脚本语言自己写一些东西。

我在各种目录中都有一些HTML文件,它们都有类似的结构:

<html>
    <head>...</head>
    <body>
        <nav>...</nav>
        <section>...</section>
    </body>
</html>

我想以编程方式将HTML部分替换为其他部分(例如,将<nav>块替换为另一个nav块[在我选择的文件中指定])我指定的文件。

我认为理想的解决方案是在Python中使用lxml或类似的东西的某种工具,但是如果有一种简单的方法可以使用* nixy工具或现有程序来执行此操作,我我很乐意这样做,而不是整理剧本。

3 个答案:

答案 0 :(得分:2)

您可以像这样使用BeautifulSoup for Python。

import BeautifulSoup

soup = BeautifulSoup.BeautifulSoup(htmldata)
nav = soup.find("nav")
nav.name = "new name"

例如:

import BeautifulSoup

html_data = "<nav>Some text</nav>"
soup = BeautifulSoup.BeautifulSoup(html_data)
nav = soup.find("nav")
nav.name = "nav2"

将更改:<nav></nav>更改为<nav2></nav2>

答案 1 :(得分:1)

不要使用正则表达式或字符串解析。那些只会让你头疼。使用解析器。

在Ruby中我会使用Nokogiri:

require 'nokogiri'

html = '
<html>
  <body>
    <nav>...</nav>
    <section>...</section>
  </body>
</html>
'
doc = Nokogiri::HTML(html)

nav = doc.at('nav').content = "this is a new block"
puts doc.to_html

哪个输出:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body>
    <nav>this is a new block</nav><section>...</section>
</body></html>

当然,您希望将"this is a new block"替换为File.read('snippet.html')

如果您的替换文件包含HTML代码段而不是nav内容,请改为使用此代码:

nav = doc.at('nav').replace('<nav>this is a new block</nav>')

输出结果相同。 (并且再次使用File.read从文件中获取该文件,如果这是你的倾向。)

在Nokogiri中,at找到由C​​SS或XPath访问器指定的标记的第一个实例,并返回Node。我上面使用过CSS,但//nav也可以使用。 at猜测访问者的类型。如果您想要具体,可以使用at_cssat_xpath,因为可能有不明确的访问者。此外,Nokogiri有search,它返回一个NodeSet,它就像一个数组。您可以根据需要迭代结果。而且,与at一样,CSS和XPath特定版本分别为cssxpath

Nokogiri有一个CLI界面,对于像这个例子这样简单的东西它可以工作,但我也可以用sed或Ruby / Perl / Python单行程来完成。

curl -s http://nokogiri.org | nokogiri -e'p $_.css("h1").length'

HTML很少这么简单,尤其是漫游狂野的任何东西,CLI或单线解决方案将迅速失控,或者只是死亡。我说这是基于多年编写许多蜘蛛和RSS聚合器 - 当你引入一个额外的HTML或XML源时,简单的开始会变得更复杂,而且它永远不会变得容易。使用解析器教会我先找他们。

答案 2 :(得分:1)

我最终编写了自己的小命令行工具来完成我想要的工作。它对我的用例非常有效,我打算随着时间的推移对其进行改进。它在GitHub上:trufflepig

我希望它对其他人也有用。