html_json用於從網頁里提取json數據。
這里用新浪讀書的書訊舉個例子,手把手寫一個html_json信息源。
打開新浪讀書的首頁,可以看到頁面下方有最新、書訊、童書、小說等幾個Tab,這里我們提取書訊的內容。

查看頁面的源碼,找不到書訊的內容。
這是因為網站使用了json技術:額外加載了json對象、並通過javascript把json的內容顯示在頁面上。
那么,怎么找到json在哪兒呢?
我用的是Firefox瀏覽器,按Ctrl+Shift+J調出“瀏覽器控制台”。別的瀏覽器也有類似的調試工具。
為了過濾掉無關的信息,在右上角的過濾里填上“sina”,這樣沒出現sina的內容會被過濾掉。

然后刷新新浪讀書的首頁,可以看到加載了大量文件,有圖片、有.css、有.js、有.html,我們要找的json就在其中。
經過一番辨認,這6個文件的可能性很大,數量正好對應網頁上的6個Tab:

我們來進行確認。右鍵點擊第2個,把鏈接復制出來,是這個鏈接:
http://feed.mix.sina.com.cn/api/roll/get?callback=jsonp1474707033326&pageid=8&lid=156&num=20&page=1
打開這個鏈接,可以看到,這是一條很簡單的javascript語句,但其中嵌入了一個很大的json對象。
try{jsonp1474707033326({"result":{"status":{"code":0,"msg":"succ"},"timestamp":"Sat Sep 24 16:58:35 +0800 2016","top":[],"pdps":[],"cre":[],"total":415,"end":1472633552,"start":1474555033,"lid":156,"rtime":1474707515
...省略中間的部分...
"comment_reply":"1","comment_show":"1","comment_total":"2","praise":"0","dispraise":"0"}]}});}catch(e){};
把最前面的try{jsonp1474707033326(和最后面的);}catch(e){};去掉,剩下的中間部分就是一個json字符串了。
復制這個json字符串,把它粘貼到http://www.bejson.com/網站,對其進行格式化,可以清晰地查看它的結構,並且確認這就是我們要找的書訊的內容。
result.data是一個列表,列表的每個元素就是一條書訊的數據。

下面是result.data里的一條數據(為了版面簡潔,去掉了一部分內容),用藍色標記出我們感興趣的內容,分別是:
title,標題
url,網址
ctime,發布時間
summary,摘要;intro,介紹。
有的數據summary為空,但intro不為空,這是網站的設計,所幸把這兩個都提取出來。
{"intime": "1474557864", "categoryid": "1", "intro": "“軟萌”肥貓“霸占”世界名畫, 還用“傲嬌”貓語解讀藝術發展? 一本《肥貓藝術課》帶你徜徉世界藝術畫廊, 告訴你“有貓的名畫,才是真跡”。", "mediaid": "0", "ctime": "1474555033", "author": "", "stitle": "《肥貓藝術課》", "images": [ { "u": "http://www.sinaimg.cn/book/2016/0922/U21P112DT20160922223234.jpg", "w": 450, "h": 476, "t": "《肥貓藝術課》 [俄]斯韋特拉娜簠靟墳娃 袁天添 北京聯合出版公司" }, { "u": "http://www.sinaimg.cn/book/2016/0922/U21P112DT20160922223418.jpg", "w": 500, "h": 363, "t": "米開朗基羅,《創造肥貓亞當》" } ], "keywords": "肥貓,名畫,藝術",
"title": "軟萌肥貓“霸占”世界名畫開講《肥貓藝術課》",
"summary": "本書是一本趣味講解藝術史的知識性讀物。本書運用生動活潑、幽默有趣的文字,向大眾普及了跨時代的藝術發展簡史。作者精心選取了不同時代、不同國籍藝術家的百余幅名畫,運用簡單的介紹性話語,介紹了這些名畫的時代背景和館藏地點,是一本簡單的“名畫藝術史”講解書。",
"productid": "0", "url": "http://book.sina.com.cn/news/b/2016-09-22/2237819373.shtml", },
已經明白了,於是寫這樣一個信息源(.xml文件),內用綠色注釋說明幾個要點:
<source> <name>新浪書訊</name> <comment>新浪圖書,書訊。</comment> <link>http://book.sina.com.cn/</link> <worker>html_json</worker> <data> <url> http://feed.mix.sina.com.cn/api/roll/get?callback=jsonp1436772833418&pageid=8&lid=156&num=20</url> <!-- 要把網址里出現的&轉義成& --> <re flags='DOTALL'> <!-- 用正則表達式去掉首、尾的javascript語句,提取json字符串到1號捕獲組 --> <![CDATA[ ^try\{\w+\( (.*) \);\}catch\(e\)\{\};$ ]]> </re> <block> <block_path>'result', 'data'</block_path> <!-- block_path是抵達數據列表的路徑。如果路徑中有列表,可以使用不加引號的數字作為列表索引 --> <title>'title'</title> <!-- 以下分別提取各項數據 --> <url>'url'</url> <summary>'summary'</summary> <temp>'intro'</temp> <pub_date>'ctime'</pub_date> </block> </data> <callback> <!-- 后處理代碼:把unix時間戳轉換成時間字符串;當summary為空時使用intro作為摘要 --> <![CDATA[ info.pub_date = unixtime(info.pub_date) info.summary = info.summary or info.temp info.temp = 0 ]]> </callback> </source>
測試一下,成功:

