爬取Arcconf文件教程並自動生成Gitbook文件顯示 - 資料獲

funnyok發表於2021-09-09

最近在接觸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檔案

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3137/viewspace-2823459/,如需轉載,請註明出處,否則將追究法律責任。

相關文章