使用Julia从HTML文件中提取和构造表

时间:2017-03-20 23:41:20

标签: html html-parsing julia gumbo

这是一个示例html文件的public link。我想从文件中提取每组CAN和年度税务信息(下图中以红色突出显示的示例),并构建一个类似于下面的数据框。

目标字段

enter image description here

示例DataFrame

| Row |          CAN | Crtf_NoCrtf | Tax_Year | Land_Value | Improv_Value | Total_Value | Total_Tax |
|-----+--------------+-------------+----------+------------+--------------+-------------+-----------|
|   1 | 184750010210 | Yes         |     2016 |      16720 |       148330 |      165050 | 4432.24   |
|   2 | 184750010210 | Yes         |     2015 |      16720 |       128250 |      144970 | 3901.06   |
|   3 | 184750010210 | Yes         |     2014 |      16720 |       109740 |      126460 | 3412.63   |
|   4 | 184750010210 | Yes         |     2013 |      16720 |       111430 |      128150 | 3474.46   |
|   5 | 184750010210 | Yes         |     2012 |      16720 |        99340 |      116060 | 3146.17   |
|   6 | 184750010210 | Yes         |     2011 |      16720 |       102350 |      119070 | 3218.80   |
|   7 | 184750010210 | Yes         |     2010 |      16720 |       108440 |      125160 | 3369.97   |
|   8 | 184750010210 | Yes         |     2009 |      16720 |       113870 |      130590 | 3458.14   |
|   9 | 184750010210 | Yes         |     2008 |      16720 |       122390 |      139110 | 3629.85   |
|  10 | 184750010210 | Yes         |     2007 |      16720 |       112820 |      129540 | 3302.72   |
|  11 | 184750010210 | Yes         |     2006 |      12380 |       112760 |             | 3623.12   |
|  12 | 184750010210 | Yes         |     2005 |      19800 |       107400 |             | 3882.24   |

其他信息

如果无法将CAN插入到可以接受的每一行,我可以单独导出CAN编号,并找到将它们附加到包含税值的数据框的方法。我已经研究过使用美丽的python汤,但我是python的绝对新手,我写的其余脚本都是Julia,所以我更喜欢用一种语言保存所有内容。

有没有办法实现我想要实现的目标?我看过Gumbo.jl但找不到任何详细的文档/教程。

2 个答案:

答案 0 :(得分:3)

因此Gumbo.jl将解析HTML并为您提供HTML文件结构的编程表示(称为DOM - 文档对象模型)。这通常是一个html标签树,您可以遍历并提取所需的数据。

为了使这更容易,您真正想要的是一种查询DOM的方法,这样您就可以提取所需的数据,而无需自己遍历整个树。 Cascadia.jl项目为您完成此任务。它建立在Gumbo之上,并使用CSS selectors作为查询语言。

因此,对于您的示例,您可以使用以下内容来提取所有CAN字段:

julia> using Gumbo

julia> using Cascadia

julia> h=parsehtml(readall("/Users/aviks/Download/z1.html"))

julia> c = matchall(Selector("td:containsOwn(\"CAN:\") + td span"), h.root)
  13-element Array{Gumbo.HTMLNode,1}:
  Gumbo.HTMLElement{:span}:
  <span class="value">184750010210</span> 
   ...
#print all the CAN values
julia> for x in c
               println( x.children[1].text )
            end

  184750010210
  186170040070
  175630130020
  172640020290
  168330020230
  156340030160
  118210000020
  190490040500
  173480080430
  161160010050
  153510060090
  050493000250
  050470630910

希望这能让您了解如何提取所需的所有数据。

答案 1 :(得分:1)

由于readall()功能不再存在,因此当前答案有点过时了。我将在下面更新他的答案。

以下是Julia软件包生态系统的一般细分(截至编写本答案时):

  • 请求用于下载HTML文件本身(请注意,在avik的回答中,他从本地计算机上读取HTML文件)
  • Cascadia 需要搜索CSS标记(例如,如果您使用Selector Gadget,就会找到标记。)
  • Gumbo 需要解析生成的HTML

要记住的关键是Gumbo以树格式存储对象HTMLNodeHTMLElement s。所以大多数对象都有父母和#34;和#34;孩子。&#34;要获得所需的数据,只需使用正确的选择器(使用Cascadia)进行过滤,然后转到Gumbo树中的正确点。

avik的答案的更新版本:

using Requests, Cascadia, Gumbo

# r = get(url) # Normally, you'd put a url here, but I couldn't find a way to grab it without having to download it and read it locally
# h = parsehtml(String(r.data)) # Then normally you'd execute this

# Instead, I'm going to read in the html file as a string and give it to Gumbo
h = parsehtml(readstring("z1.html"))

# Exploring with the various structure of Gumbo objects:
println(fieldnames(h.root))
println(fieldnames(h.root.children))
println(size(h.root.children))

# aviks code:
c = matchall(Selector("td:containsOwn(\"CAN:\") + td span"), h.root);
for x in c
    println( x.children[1].text )
end

这个特定网页比大多数网页更难刮,因为它没有很好的CSS结构。

Cascadia README上有关于工作流程的一些很好的文档,但在阅读之后我仍然有一些问题。对于其他任何人(比如我,昨天)来到此页面寻找Julia网页抓取的指导,我已经创建了一个jupyter notebook,其中包含一个简单的示例,希望能帮助您更详细地了解工作流程