如何在bash中解析html?

时间:2016-05-18 19:35:27

标签: html bash

从我收集的内容来看,在Bash中解析html通常被认为是一个坏主意。但是一个人从来没有学过骑自行车而且在这个过程中也没有下降几次。

所以,使用Bash,我试图从html网页中提取一些数据。我想要获取的相关部分是data-nick="someguy99",这是一个用户名,然后直接在下面的行上显示消息"Hello. This is the data I wish to obtain."

<body>
 <div id="main">
  <div class="content">
   <div class="block">
    <div class="section">
     <div class="chat-holder">             
      <div class="chat-box">  
       <div class="chat-list">
        <div id="0" class="text" style="color: rgb(73, 73, 73);">
         <span class="username messagelabel" data-nick="someguy99">someguy99:</span>  
         "Hello. This is the data I wish to obtain."

使用wget我无法遍历"chat-list"。我已经尝试将输出管道传输到其他程序wget -O - http://website.url | lynx -source -dump但是没有任何工作。总是相同的输出。例如:

wget --quiet -F -O - http://website.url/example | \
lynx -dump -source -stdin | grep 'chat-list'

和结果......

 
        var img = $('.chat-list img[title="' + slug + '"]');

这与使用Web浏览器时在文档树中看到的输出不同。将grep 'chat-list'替换为grep 'data-nick'会返回根本没有匹配的模式。

我做错了什么?如何更深入地解析以获取我寻求的数据?

我的大脑现在感觉有点油腻,所以如果我遗漏任何相关信息,请告诉我,我会提供更多细节。

  • Mac OS X 10.11.5
  • GNU bash 4.3.42

谢谢。

2 个答案:

答案 0 :(得分:2)

可悲的是,您在Safari的Web Inspector中看到的是 HTML页面的文本。它是浏览器解释页面的结果,可能包括执行嵌入式Javascript程序和从其他页面读取的数据。此外,Web Inspector向您显示完全嵌套的树结构,即使原始HTML可能缺少关闭标记甚至一些开始标记:这样的一个典型示例是您将始终在<tbody>内部看到<table>元素{1}}元素,即使HTML页面不包含带有tbody标记的单个元素。

因此,wgetwget | lynx -source向您显示相同的数据并且通过grep的管道找不到您在Web检查器中看到的行,这并不奇怪。该行根本不存在于网页的来源中;它是Web Inspector解释组合页面对象的内部表示的结果。

据我所知,虽然有一些实验支持,但普通的文本模式浏览器都没有实现Javascript。此外,(据我所知,对于常见的文本模式浏览器),不支持转储DOM(&#34;域对象模型&#34 ;;即Web Inspector显示的实际对象树) )。文本模式浏览器倾向于为您提供-dump选项,以将呈现的输出显示为文本,或-source显示原始HTML文件。

在我看来,处理客户端生成的页面的最佳方式 - 即在本地Web浏览器加载页面期间组装的页面 - 是使用headless browser,例如PhantomJS (维基百科文章中列出了其他一些,但我只有PhantomJS的经验)。或者,您可以尝试使用Selenium等浏览器自动化工具,它可以让您编写浏览器脚本。或者,在Mac OS X上,您可以使用Applescript编写Safari浏览器的脚本。 (我不再使用Mac,但Safari Applescript字典显示您可以open使用网址do javascript在该网页内执行javascript。)

不幸的是,这些技术都没有充分记录(恕我直言),而且存在哪些文档往往侧重于单元测试网页(这是一个非常重要的用例,但不一定与数据抓取有关)。我发现PhantomJS开始时非常烦人,直到我发现你试图在网页内执行的javascript中的任何语法错误导致PhantomJS只是挂起而没有创建任何错误消息。因此,在PhantomJS中尝试使用Node等语法检查脚本之前,使用其他一些javascript解释器至关重要。

在网页中运行的javascript程序中,您通常可以使用JQuery进行导航,这使得根据属性值(如您的问题中)查找内容非常简单。对于页面尚未导入JQuery的情况,PhantomJS提供了一种机制,可以为您将JQuery注入到页面中,但我从未使用过。

祝你的项目好运。

答案 1 :(得分:1)

我拿了你的HTML片段并将其写入tmp文件。 然后我使用Rubular.com根据您的要求构建了一个正则表达式, 然后我在它上面运行了grep -P,结果很接近:

#> grep -Pzo 'data-nick="[^>](.+|\n)[^"|\n]+"' /tmp/test.html
data-nick="someguy99"

然而,你需要的是一些覆盖多行的方法,我认为|\n会这样做,但不是很 - 抱歉!我使用Ubuntu 14.04并将grep切换到PCRE(非POSIX模式),所以你可能想要指定你的O / S和bash版本,因为我相信在不同系统上有不同版本的grep。