为了账号安全,请及时绑定邮箱和手机立即绑定

爬取Arcconf文档教程并自动生成Gitbook文档显示 - 数据获取

标签:
Python 爬虫 Git

最近在接触Arcconf之类的命令操作和Gitbook,所以结合起来做个练习

1. 数据获取

    页面构成大致如下,每个版块都分为标题、命令功能、命令格式、参数说明(表格)、使用指南、使用实例几个部分

图片描述

图片描述

2. 流程分析

    数据方面难点应该是表格、命令和实例方面,表格正好可以使用之前自己写的htmlmarkdown(参见以前文章),命令的话这里也存在着可能有多行命令的情况所以要分开处理,实例因为又涉及代码又设计文字,而且html中并没有明显的区分格式,所以直接将代码归一类,文字作为标题(反正代码都是跟命令走的嘛,看命令就能知道注释含义,就当做标题了),整个Html文档的区分性不强,很多板块的class值都是一样的,里面也是各有特点,有些表格直接p标签显示,有些还要加pre、strong、em甚至表格嵌套,所以xpath直接抓取显然不明智(其实也可以直接全部获取,然后根据位置分门别类,感觉麻烦到不可能实现),所以这里主要采取re正则处理,xpath作为辅助处理一些小格式问题

3. 数据抓取

I. 网页内容获取

爬虫基础嘛,老一套,不是很隐秘的网站,所以header什么的其实不所谓,看习惯和心情吧

def get_html(url):
    r = requests.get(url, headers=headers)
    return r.text

II. 处理冗余标签

如上所述,很多不必要的标签会混淆,所以去除

def get_data_html(text):
    text = re.sub('</strong>', '', re.sub('<strong.*?>', '', re.sub('</em>', '',         
    re.sub('<em.*?>', '', text))))
    html = etree.HTML(text)

III. 获取标题、命令功能

    这里只有标题是h4标签,所以很方便抓取,命令功能和也比较明显,用正则还是很方便的

title = re.findall('<h4.*?>(.*?)</h4>', text)#列表
function = re.findall('<h5.*?>命令功能</h5>.*?<p.*?>(.*?)</p>', text)#列表

IV. 获取命令格式、使用指南

    因为这几项都是不唯一的,使用正则就不是很明智了(主要是自己也学的不好),然后我们用xpath结合containsparent树结构获取,使用列表保存,之后要生成文件嘛,因为这两项的值都不唯一,所以重写一个方法获取相应数据,将数据以列表形式保存,返回给外层列表,即是列表包含列表的嵌套结构,这里的div是父层元素的lxml位置,可以直接调用这个来执行xpath索引

def get_data_html(text):
    order = []
        order_divs = html.xpath('//h5[contains(text(), "命令格式")]/parent::div')
        for div in order_divs:
            order.append(get_order(div))

    tutor_divs = html.xpath('//h5[contains(text(), "使用指南")]/parent::div')
        tutor = []#保存使用指南的嵌套列表
        for div in tutor_divs:
            tutor.append(get_tutor(div))


def get_order(rule):
    tmp = []
    if len(rule.xpath('./p')) > 1:
        for data in rule.xpath('./p'):
            tmp.append(" ".join(data.xpath('.//text()')))
    else:
        tmp.append(" ".join(rule.xpath('./p//text()')))
    return tmp


def get_tutor(div):
    tmp = []
    if div.xpath('.//p[@id]'):
        tmp.extend(div.xpath('.//p[@id]//text()'))
    if div.xpath('.//div[@class="idp-ltr-html-noticebody"]'):
        tmp.extend(div.xpath('.//div[@class="idp-ltr-html-noticebody"]/p//text()'))
    return tmp


V. 获取参数说明(表格)

之前有专门写过htmlmarkdown的程序,这里现般现用就行,所以主要两个任务:1. 获取到每个表格的html字符串 2. 对表格内的数据处理做一定修改,因为这里表格内的结构不一,有些表格甚至涉及嵌套规则

  • 表格class唯一,所以直接获取
  • 主要难点在于对于表格内多行数据怎么获取,这里在以前的基础上修改,针对多行数据李彤try、except捕获异常,有异常即说明数据不唯一,针对数据改变xpath索引为'./td/ul/li//text()或者'./td//text()'等其他规则,但是因为这里部分表格在td之上有一层p标签,导致//text()获取不到之后的内容(其实还好,只有连个表格涉及这种情况,手动处理就好了嘿嘿嘿),所以更好的方法就是哈哈哈,对没错用re将p标签去除,只保留里面文字即可,像这样re.sub('<p.*?>', '', text)
  • print_datawrite_data分别是打印和写入文件的操作,详情参考之前的文章
def get_data(table):
    html = etree.HTML(table)
    body = []
    head = html.xpath('//table/thead/tr')
    # 获取表头
    title = [th.xpath('.//p//text()') for th in head][0]
    # #根据表头长度确定符号线
    line = ["----"] * len(title)
    # 获取表格内容并用嵌套的列表保存
    tbody = html.xpath('//table/tbody/tr')
    for tr in tbody:
        body.append(list_format(tr, len(title)))
    return title, line, body


def list_format(rule, num):
    tmp = []
    for i in range(num):
        try:
            data = rule.xpath('./td/p//text()')[i]
            tmp.append(data)
        except:
            data = " ".join(rule.xpath('./td[{}]/ul/li//text()'.format(i+1)))
            tmp.append(data)
    return tmp


def print_data(table):
    title, line, body = get_data(table)
    # 用"|"分隔获取到的数据并依次打印
    result = [" | ".join(data) for data in body]
    print("| " + "| ".join(title) + "|")
    print("| " + " | ".join(line) + "|")
    for data in result:
        print("| " + data + "|")


def write_data(table, filename):
    title, line, body = get_data(table)
    result = [" | ".join(data) for data in body]
    with open(filename.replace('/', '_'), 'a', encoding='utf-8') as f:
        f.write("| " + "| ".join(title) + "|" + "\n")
        f.write("| " + " | ".join(line) + "|" + "\n")
        for data in result:
            f.write("| " + data + "|" + "\n")

VI. 获取实例

实例用xpath确认到对应的div后分别用列表保存标题(文字)和代码即可

def get_data_html(text):
    exams = []
    exams_title = []
    exams_html = html.xpath('//h5[contains(text(), "使用实例")]/parent::div')
    for exam in exams_html:
        tmp_title, tmp = get_exams(exam)
        exams_title.append(tmp_title)
        exams.append(tmp)
    return title, function, order, tabs, tutor, exams_title, exams

def get_exams(div):
    tmp, tmp_title = [], []
    if div.xpath('./p[@id]'):
        tmp_title.extend(div.xpath('./p[@id]//text()'))
    if div.xpath('.//pre'):
        for pre in div.xpath('.//pre'):
            single = pre.xpath('./text()')
            tmp.append("".join(single))
    return tmp_title, tmp

至此我们已经拿到了所有数据,下一节介绍怎么写入Gitbook文件

点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消