推荐学习书目
› Learn Python the Hard Way
Python Sites
› PyPI - Python Package Index
› http://diveintopython.org/toc/index.html
› Pocoo
值得关注的项目
› PyPy
› Celery
› Jinja2
› Read the Docs
› gevent
› pyenv
› virtualenv
› Stackless Python
› Beautiful Soup
› 结巴中文分词
› Green Unicorn
› Sentry
› Shovel
› Pyflakes
› pytest
Python 编程
› pep8 Checker
Styles
› PEP 8
› Google Python Style Guide
› Code Style from The Hitchhiker's Guide
MrhuangSTR
V2EX  ›  Python

各位大佬有什么好的办法解析网页中不规整的表格吗

  •  
  •   MrhuangSTR · Feb 20, 2020 · 5452 views
    This topic created in 2448 days ago, the information mentioned may be changed or developed.

    像几乘几这种规整的表格到很好解析,xpath 或者 bs4 或者 pandas 的 read_html 可以搞定,但是遇到那种不规整的表格,而且整个网站的表格样式可能都不一样,有什么好的办法做到通用解析,例如这个网站的表格

    Supplement 1  ·  Feb 20, 2020
    **表格是这个网站里的每条公告里的表格**
    36 replies  •  2020-05-26 10:32:59 +08:00
    MrhuangSTR
    MrhuangSTR
    OP
    Feb 20, 2020
    1
    大佬在哪里 f(;´д`)ゞ
    akira
    akira
    Feb 20, 2020
    2
    这个不是表格吧。。。
    deplives
    deplives
    Feb 20, 2020
    3
    这哪里有表格?
    qazwsxkevin
    qazwsxkevin
    Feb 20, 2020
    4
    依然用 for bs4 吧
    每个 div 下面有 ul
    每个 ul 下面有 5 个 li
    很明显的特征,性能不好的写法是啰嗦写多几个字典,逐个判断,逐个加
    不知道有无更好性能方法了
    MrhuangSTR
    MrhuangSTR
    OP
    Feb 20, 2020
    5
    @akira 额 点进去每个公告里的表格
    MrhuangSTR
    MrhuangSTR
    OP
    Feb 20, 2020
    6
    @deplives 每个公告的表格。。
    MrhuangSTR
    MrhuangSTR
    OP
    Feb 20, 2020
    7
    @qazwsxkevin 公告里的表格。。
    qazwsxkevin
    qazwsxkevin
    Feb 20, 2020
    8
    @MrhuangSTR 我能想到的是找出这个表格的 table 标签,然后对每个 tr 段,再对每个 td 做 get_text()了
    然后再洗数据加进字典
    就看了几个页面,似乎都差不多格式
    deplives
    deplives
    Feb 20, 2020
    9
    @MrhuangSTR 请善用浏览器调试功能
    ![]( )
    superrichman
    superrichman
    Feb 20, 2020 via iPhone
    10
    这种不规则的表格没有通用的解析方法,自己一个一个遍历元素取数据吧。还有这是个 gov 网站,如果你是想做爬虫的话,小心点别变成了 ddos 攻击 zf 网站。 /doge
    MrhuangSTR
    MrhuangSTR
    OP
    Feb 20, 2020
    11
    @qazwsxkevin 每个栏目下分页基本上都有 120 页,可能前 1 到 20 页里的公告表格样式基本一致,某个区间段的表格格式又是另外一种,我现在大概看了下有 4 种不一样的表格,可能还有更多种。
    MrhuangSTR
    MrhuangSTR
    OP
    Feb 20, 2020
    12
    @deplives 没这么简单的,多点开几个表格看看你会发现惊喜的 /doge
    MrhuangSTR
    MrhuangSTR
    OP
    Feb 20, 2020
    13
    @superrichman 我 ip 今天就被 ban 了。。。。我都是很佛系的抓
    autoxbc
    autoxbc
    Feb 20, 2020
    14
    都是很标准的表格,看不出有什么问题,最多有跨单元属性 colSpan 和 rowSpan,也是 html 标准之中的
    L2AKnG8GXx60bc6P
    L2AKnG8GXx60bc6P
    Feb 20, 2020 via iPhone
    15
    我做过
    MrhuangSTR
    MrhuangSTR
    OP
    Feb 20, 2020
    16
    @autoxbc 表格没啥问题,棘手的是怎么写一个通用的方法解析整站不同样式的表格
    MrhuangSTR
    MrhuangSTR
    OP
    Feb 20, 2020
    17
    @relic 有什么好的办法分享下呗大佬
    metamask
    metamask
    Feb 20, 2020
    18
    应该是没有通解办法,

    用 table 做的时候,他们都是直接怼进去 td 里面。

    有个办法你可以尝试下, 你先做一个判断是不是标题的函数, 然后扔进去解解看。
    比如最后带 ":" 判断为 label。

    但实话说,我觉得这个很难洗干净,至少不是一下子能洗干净。
    metamask
    metamask
    Feb 20, 2020
    19
    但这类垂直爬取 有一个好处

    你可以自己先拿几个 做个处理就干净很多。
    比如你判断 “面积” 为 label 的时候,通过对比,知道一般他是在下一个 tr 里面,你写 parse 的时候,就把 2 个 tr 合起来,
    直接默认拿 tr_1.td_1: tr_2.td_1, tr_2: td_2
    metamask
    metamask
    Feb 20, 2020
    20
    这种要洗干净你可以这么做。

    先下下来,随便拿一个,把表格洗了,然后字段扔进去 mapping, 如
    {
    "面积": parse_rule_1,
    }

    parse_rule_1(table, td)
    td = td. next_tr.td[index]
    table.pop(td)

    最后如果 table 里面还有元素的话,那么就是有新的元素,直接报错。
    你再手动去处理下。
    wangyzj
    wangyzj
    Feb 20, 2020
    21
    不得不说国土资源部的网站做的还是挺清秀的
    akira
    akira
    Feb 20, 2020
    22
    不要管 trtd, 全部内容提取出来,然后再统一清洗
    encro
    encro
    Feb 20, 2020
    23
    直接使用 xpath 或者 css 遍历,最简单网站了。
    encro
    encro
    Feb 20, 2020
    24
    原来是表格啊。
    不太可能有通用的,因为表格就不规范。
    你只能根据不同类型自己去写解析程序了。

    提示下:
    table 的 tr 下是 td,td 有两个属性,rowspan 和 colspan,它们的值就是分析表格的关键。但是对于这种不规则的,只能自己写程序,看有多少种类型,就微调下吧。
    TimePPT
    TimePPT
    Feb 20, 2020
    25
    换个思路,全部抓图然后表格 ocr 接口识别
    locoz
    locoz
    Feb 20, 2020
    26
    无解。先拿下来再处理吧,按特征分成一类一类地处理,慢慢的就处理完了。
    然后建议用 GUI 标记工具(指类似于 pyspider、各种傻瓜式爬虫工具的点页面元素自动输出 xpath 到对应采集字段上的)辅助,要不然手写 xpath 很蛋疼。
    MrhuangSTR
    MrhuangSTR
    OP
    Feb 21, 2020
    27
    @freakxx 标题有的带冒号有的不带。。
    另外你举的这个面积的例子,烦就烦在可能在其他表格里它对应的值就和它在一个 tr 里而不是下一个 tr;
    后面你说的这个方法应该是在已经确定需要哪些字段的情况下再去 mapping
    MrhuangSTR
    MrhuangSTR
    OP
    Feb 21, 2020
    28
    @akira 清洗规则很难定
    MrhuangSTR
    MrhuangSTR
    OP
    Feb 21, 2020
    29
    @locoz 这里的 xpath 倒不是很杂,看来只能分多种情况了
    hitaoguo
    hitaoguo
    Feb 21, 2020
    30
    建议楼主贴几个不同类型的表格网址出来。
    metamask
    metamask
    Feb 21, 2020
    31
    @MrhuangSTR

    你多抓几份看看就可以了,
    位置相对是固定的。

    你事先做一份已经确定不就好?如果没 map 到,再手动补上去,这个工作总能完成的。
    MrhuangSTR
    MrhuangSTR
    OP
    Feb 21, 2020
    32
    @freakxx 这是个体力活啊,终于是搞定了。。
    Skyline57
    Skyline57
    May 19, 2020
    33
    @MrhuangSTR 同病相怜啊楼主,我最近也是在搞这些 ZF 的数据,不过我好像解决了,找到了一种通用的方式
    我用的 xpath ( xpath 还是挺好使的),把键和值分开来获取,最后再 zip 到一起
    原理是:td 位置为奇数则是键,为偶数则是值
    (键为土地编号、面积等,值为据图数值)
    获取键的表达式:"//table//table//td[position() mod 2 = 1]"
    获取值的表达式:"//table//table//td[position() mod 2 = 0]"

    但是,提取之后会发现有的键是没有对应值的(比如“主要用途”那栏的值是空的)
    这时就要把没有对应值的键单独提出来
    观察几个网站发现没有对应值的键的相似之处为:都有 colspan="3"或者 colspan="6"的属性

    所以
    提取的 xpath 表达式为:'//table//table//td[position() mod 2 = 1][@colspan="3" or @colspan="6"]'

    最后把没有对应值的键都从所有键中剔除或者设为空,其他键值对一一对应即可

    .......
    .......

    最后发现出了点小问题

    呃呃呃,:面积"那栏键值是竖着的,不是向其他的那样横着的,也就是上述的最终键值对被污染了
    但是对"面积"这对键值单独处理下,应该问题不大,思路是用 xpath 获取到 text()为"面积"的 td 节点,再通过这个节点的父级 tr 的下一位置 tr 下的 td 获取到面积的数值,再从键列表中删除"面积",值列表中删除面积的值

    最后终于大功告成
    MrhuangSTR
    MrhuangSTR
    OP
    May 25, 2020
    34
    @Skyline57 我跟你的解析思路一样的,花了我一天的时间,这玩意太折磨人了
    Skyline57
    Skyline57
    May 25, 2020
    35
    @MrhuangSTR 我还遇到过一个网页里两三种编码的,真是吐了
    MrhuangSTR
    MrhuangSTR
    OP
    May 26, 2020
    36
    @Skyline57 编码还好吧,一个网页有几种非常规的字体的你遇到过吗 ̄へ ̄
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1412 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 19:15 · PVG 03:15 · LAX 11:15 · JFK 14:15
    ♥ Do have faith in what you're doing.