python 使用lxml requests抓取某網站的幫助文檔

目標網站 http://help.tongtool.com/service.html?groupId=2

抓取的數據分析:先從html源代碼分析,發現幫助文檔的內容,都不存在於源代碼中,所以不能直接用request.get("http://help.tongtool.com/service.html?groupId=2")來獲取了。F12查看接口請求信息,一共包含兩個請求url

http://help.tongtool.com/category/buildCategoryTreeHavingChildren 和http://help.tongtool.com/docs/listDocsPage?categoryId=306&pageSize=20&pageNum=1,查看兩個請求的返回結果,第一個返回了了整個幫助文檔的目錄結構,部分返回數據如下:

第二個請求返回就是我們需要抓取的幫助信息詳情了

從返回的結果裏面,可以看到有我們需要抓取的信息有標題、內容、圖片。再分析第二個請求url的結構,有一個關鍵詞categoryId=306 感覺幫助文檔的每個幫助信息,應該就是通過這個iD信息來存儲的。於是嘗試點擊另一條幫助信息,查看請求的url,兩者進行比較,果然是隻有這個categoryId的值發生的改變。

以上綜述,就是隻要獲取到所有幫助信息對應的categoryId,然後通過http://help.tongtool.com/docs/listDocsPage?categoryId=306&pageSize=20&pageNum=1這個鏈接,來改變categoryid的值,就可以循環獲取到所有的幫助內容了。那麼接下來就是如何獲取所有的categoryid了。

獲取categoryid

此時再回頭看第一個鏈接的返回結果,不難看出返回的json中,有很多的id,並且每個id都不一樣,這個時候就可以試想這裏的id是不是就是我們需要的categoryid呢?我們可以做如下驗證,我們以下面這個爲例子

可以看到id235對應的幫助信息是其他導入方式,那麼我們將235替換後訪問試試,返回的結果如下:

這麼一看,兩者的信息就對應上了,接下來就是如何去獲取所有id了。通過對json格式的分析,我們很容易就能掌握規律,這裏就不做敘述了。大致獲取的方法如下:

def categoryId():
    "獲取文檔對應的id"
    document_page=requests.get("http://help.tongtool.com/category/buildCategoryTreeHavingChildren")
    ducument_result = document_page.json()
    erp_help=ducument_result.get('datas')[0].get('childrenList')[0]  #get('childrenList')[0]爲ERP [1]爲listing []

    "得到幫助文檔內容"
    help_infos=erp_help.get('childrenList')[0].get('childrenList')
    categoryIds=[]
    for i in help_infos:
        "獲取一級菜單下面的子信息"
        sub_info=i.get('childrenList')  #list
        for j in sub_info:
            categoryIds.append(j.get('id'))
    return  categoryIds

這樣就獲取到了所有的categorys了

循環獲取每條幫助內容

已知所有的categoryid後,剩下的就是依次通過每個id,來獲取具體的幫助信息了。可以先拿一個id作爲例子,實現玩一個後,再最外層套上循環就可以了。

page=requests.get("http://help.tongtool.com/docs/listDocsPage?categoryId=189&pageSize=20&pageNum=1")
result=page.json()
contents=result.get('datas').get('list')
for content in contents:
    "存在多個的時候逐個讀取"
    all_contents = ""    #幫助文檔內容
    title = content.get('title')  #標題
    if ":" in title:
        title=title.split(":")[0]  #存在一個報錯的地方,先這麼處理
    if not os.path.exists('d://tmp//{0}'.format(title)):
        os.makedirs('d://tmp//{0}'.format(title))
    file_text = '{0}.txt'.format(title) #每條幫助信息一個文檔,用標題做文件名
    content_text = content.get('content')
    html = etree.HTML(content_text)  #使用etree來處理結果
    "解析文本內容"
    html_contents = html.xpath("//*/text()")  #通過xpath來獲取幫助內容
    for html_content in html_contents:
        all_contents = all_contents + html_content + '\n'
    "解析幫助圖片"
    html_pages=html.xpath("//img/@src")
    "創建文件夾來存儲圖片"
    for page in html_pages:
        filename = page.split('/')[-1]
        print ('準備下載:'+page)
        “url過濾和格式化”
        if 'help' not in page:
            print ('過濾鏈接:'+page)
            continue
        if "http" not in page:
            page="http:"+page
        ur.urlretrieve( page, os.path.join("d://tmp",title,filename))
    file = open('d:\\tmp\\{1}\\{0}'.format(file_text,title), 'w', encoding='utf-8')
    file.write(all_contents)

這裏說明下,一個ID所對應的幫助信息可能是多條的,如下圖,存在多條的時候就要循環逐個讀取了。

這樣執行後,就會生成多個文件夾,每個文件夾是一個幫助信息,裏面存儲了幫助信息的所有內容,包含圖片和文本。

這樣就實現了一個id的所有幫助信息抓取,接下來就是循環來讀取categoryid,來獲取所有的幫助信息了。

以上只是一個簡單的實現,接下來需要優化的地方包含1、多線程的處理  2、讀取數據存儲到數據庫 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章