html - 使用Text.XML.Cursor获取特定的HTML表列

标签 html parsing haskell xpath xml-parsing

我正在尝试使用Haskell和Text.XML.Cursor包解析HTML页面。我的目标是返回列表中的第三列值。我花了最后4个小时尝试使其正常运行。但是,似乎我无法理解XPath和Text.XML.Cursor在概念上如何工作。

因此任务是:


在文档中的某处找到<table class="forumTable">标记
对于其中的每个<tr>标签,请使用第三个<td>标签
单元格内有一个<a>标记,我要将其添加到列表中。不是content属性,而是href<a>之间的值


具体来说,我正在解析this link,并且尝试获取带有论坛名称(主题之后的下一个)的列的值。

据我所知。似乎正在返回表内</a>标记的所有内容

findNodes :: Cursor -> [Cursor]
findNodes = element "table" >=> attributeIs "class" "forumTable" &// element "tr" &/ element "td" &/ element "a" >=> child
extractData = T.concat . content
...
let cursor = fromDocument $ parseLBS $ simpleHTTP "http://www.sql.ru/forum/sqlru-3-days/2"
let lines = cursor $// findNodes &| extractData


我正在寻找解决我的问题的方法,并寻求这一切如何工作的解释。谢谢。

最佳答案

我知道了!

考虑以下输入文件:

<html>
  <head>
    <title>Haskell XML Parsing Example</title>
  </head>
  <body>
    <table class="forumTable">
      <tbody>
        <tr>
          <td> <a href="#1">1</a> </td>
          <td> <a href="#2">2</a> </td>
          <td> <a href="#3">3</a> </td>
          <td> <a href="#4">4</a> </td>
        </tr>
        <tr>
          <td> <a href="#5">5</a> </td>
          <td> <a href="#6">6</a> </td>
        </tr>
        <tr>
          <td> <a href="#7">7</a> </td>
          <td> <a href="#8">8</a> </td>
          <td> <a href="#9">9</a> </td>
          <td> <a href="#10">10</a> </td>
          <td> <a href="#11">11</a> </td>
        </tr>
      </tbody>
    </table>
  </body>
</html>


和Haskell代码:

{-# LANGUAGE OverloadedStrings #-}

import qualified Data.Text.IO as T
import Text.XML.Cursor
import Text.XML

select3rd :: Name -> Axis
select3rd name =
    helper . (child >=> element name)
  where
      helper (_:_:x:_) = [x]
      helper _         = []

findNodes :: Cursor -> [Cursor]
findNodes =
    element "table" >=> attributeIs "class" "forumTable"
        &// element "tr" >=> select3rd "td"
        &/ element "a"

main :: IO ()
main = do
    doc <- Text.XML.readFile def "res/test.html"
    let cursor = fromDocument doc
    mapM_ T.putStrLn (cursor $.// findNodes &/ content)


在了解所有这些运算符($.//&/等)的工作方式之前,需要花费一些时间,但是在阅读了documentation几次并将它们一起使用之后,情况会变得更好。另外,建议您仔细阅读解释CursorAxis是什么的部分。

上面的代码按如下方式工作(按惯例)。首先,使用提供的库函数将maincursor放入文档的根目录。然后我们一起组成cursorfindNodescontent。运算符$.//表示findNodes必须在当前游标(cursor)及其所有后代的上下文中运行。换句话说,这只是意味着findNodes将可以访问整个HTML树。试试看,并使用$/代替$.//。您会注意到,findNodes不会使用<table>找到element "table"元素,因为<table>不在<html>下方(这是cursor当前指向的位置)。然后,在findNodes中,我们使用element "table"运算符组成attributeIs "class" "forumTable">=>,因为右侧(rhs)的函数必须在左侧(lhs)返回的Axis上执行。

之后,我们使用&//运算符过滤<tr>内部的后代<table>。和以前一样,如果只使用&/,则不会找到<tr>,因为其中有一个封闭的<tbody>标记,并且&/仅看起来是直接后代(或子代)。注意,当lhs中有一个Cursor时,运算符以$开头,而当我们有Axis时,它们以&开头。最后,我们有select3rd轴,该轴允许在存在节点的第三个子节点时进行命名选择。我们用它来选择每个<td>中的第三个<tr>。希望到现在,应该很容易理解它是如何工作的。

您问题中的代码在child末尾使用findNodes运算符调用>=>。只要将&/之前的content更改为>=>,就可以保留该调用(两个实现都是等效的)。

关于html - 使用Text.XML.Cursor获取特定的HTML表列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44212378/

相关文章:

javascript - 如何使用 javascript/jquery 更改每行文本的文本方向?

r - 如何解析自定义格式的文件 R

mysql - 使用mysql解析json

Haskell 列表理解创建函数

javascript - anchor 位置等于位置减去标题高度

javascript - jQuery:使 div 可点击以检查嵌套的复选框

javascript - 如何使用 Jquery 设置数据属性?

java - 如何解析字符串并根据java中不同定义的模式使用它?

haskell - Haskell 中的所有图形和网络库是如何实现的?

元组的 Haskell 类型类