目標網站 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、讀取數據存儲到數據庫