nodejs環境下html的解析
nodejs環境下,對妹子圖網站的資料進行取得/解析/並利用express對客戶端進行json數據的回傳。
本文主要解決了:1.jquery解析請求過來的html如何實現的問題;2.nodejs環境下jquery重度使用者的替代函數庫的問題;3.nodejs下,如何發送ajax請求的問題(ajax請求,本身就是一個request請求);4. 本文用實際的案例來介紹如何使用cheerio
進行進行dom操作。
使用者需要安裝npm模組:cheerio
另外推薦使用npm模組:nodemon,可以對nodejs的程式進行熱部署
微信小程式平台的基本需求是:
1. 資料伺服器必須要是https協定的service介面
2. 微信小程式不是html5,不支援dom解析和window操作
3. 測試版本可以用第三方的資料服務接口,正式版本不允許用第三方的接口(當然,這裡說的是多個第三方資料接口)。
在APICLOUD平台下,我們可以使用html5配合jquery等類別庫來實現dom資料的解析,來解決資料來源不是json格式的問題( html下利用jquery載入html5中的數據,回頭整理一下之前學習apicloud平台api的時候,做的測試app),但是在微信小程式平台下,解析html元素基本上是沒有辦法的。在本文撰寫之前,我在網路上看到有說用underscore
來代替jquery做dom解析的回答,我搞了半天,發現還是不是那麼順手。
因此,本文提出的方案是為了解決兩個問題:
1. 利用自己的伺服器,為自己的微信小程式提供第三方網站的html資料轉換服務,將第三方的 html元素解析出自己需要的元素,在nodejs平台下,利用request
模組來完成資料請求,利用cheerio
模組來完成html的解析。
2. 在nodejs平台下,雖然有jquery模組,但用起來還是有很多問題的。網路上有一貼被給個網站複製的帖子,給出的在nodejs環境下使用jquery的方法,經過我的實際測試,發現並不能順利的進行上手編寫程式碼。
因此,本文的行文思路:1. 對資料來源進行分析; 2. 對request
進行簡單的介紹;3.對cheerio
模組的常用方法進行簡單的介紹;4. 寫在nodejs下,利用express
模組來實作json資料的提供。
依照大多數程式的套路,對第三方資料來源的操作多是爬蟲案例,那麼本文的案例應該也是宅男福利了吧。本文的目標網址是:http://m.mmjpg.com
.
#本文的資料來源是來自排行榜頁。 排行榜頁面長這樣,
滑動滾動條在對底部,我們可以發現有一個加載更多的按鈕,點擊載入更多之後,在瀏覽器的控制台中,可以看到,瀏覽器發送了一個url
為http://m.mmjpg.com/getmore.php ?te=1&page=3
的請求.
瀏覽器的控制台顯示的網路請求截圖如下圖所示:
我們可以用瀏覽器,打開上面這個連結(http://m.mmjpg.com/getmore.php?te=1&page=3
),這是我在寫本文的時候,訪問這個連結時瀏覽器獲取到的即時數據(讀者在自己進行瀏覽器存取時,可能獲取的數據和我的不一樣)。
下圖中,我對頁面原始碼中的資料進行了標註,包括一下內容:1. 標題;2.所有圖片的瀏覽位址;3.預覽圖的位址;4.發佈時間;5.按讚次數
對上面我們造訪載入更多頁面時,取得的page=3的清單的頁面中,點擊了下面這個連結http://m.mmjpg .com/mm/958
,對應的標題是亮麗清純妹冰露純天然的G杯巨乳美圖
。
從上圖中,可以看到,每個http://m.mmjpg.com/mm/958/<a href="//m.sbmmt.com/wiki/58.html" target="_blank">陣列</a>序號
頁面都有一張圖片,而這張圖片的位址也很規範,為http://img.mmjpg.com/2017/958/1.jpg
。那後面的事情就很簡單了,我們只需要知道目前圖片集一共有多少張,就可以依照規則來拼接出所有圖片的地址了。那這裡,對詳情頁資料的獲取,我們只需要對第一個圖片的頁面進行資料的獲取就可以了。主要取得的資料是第(1/N)張
和class
為content
的p下面第一個img
標籤的src就可以了。
那,上面對資料來源的介紹,就是這麼多,其他的資料來源的分析都是這樣的一個想法。相信列位看官一定能夠得到自己想要取得的資料。
request
#模組讓http
請求變的更簡單。
var request = require('request'); request('http://www.google.com', function (error, response, body) { if (!error && response.statusCode == 200) { console.log(body); } })
var fs=require('fs');var request=require('request'); request('http://n.sinaimg.cn/news/transform/20170211/F57R-fyamvns4810245.jpg').pipe(fs.createWriteStream('doodle.png'));
fs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))
request.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))
var r = request.post('http://service.com/upload')var form = r.form() form.append('my_field', 'my_value') form.append('my_buffer', new Buffer([1, 2, 3])) form.append('my_file', fs.createReadStream(path.join(dirname, 'doodle.png')) form.append('remote_file', request('http://google.com/doodle.png'))
request.get('http://some.server.com/').auth('username', 'password', false);
//User-Agent之类可以在options对象中设置。var options = { url: 'https://api.github.com/repos/mikeal/request', headers: { 'User-Agent': 'request' } };function callback(error, response, body) { if (!error && response.statusCode == 200) { var info = JSON.parse(body); console.log(info.stargazers_count +"Stars"); console.log(info.forks_count +"Forks"); } } request(options, callback);
cheerio為伺服器特別定制的,快速、靈活、實施的jQuery核心實現.npm官網下對cheerio模組的簡介:www.npmjs.com/package/cheerio
如果閱讀英文文獻有問題的話,nodejs中文社群下的關於cheerio的api的中文介紹:cnodejs.org/topic/5203a71844e76d216a727d2e
其實,如果在nodejs下,使用const cheerio = require('cheerio');
這樣的方式載入cheerio
模組的話,將我們的html來源字串作為參數,利用cheerio
的load
函數進行載入的話,我們是可以完全按照在jquery
環境下的程式思路,來實現對dom的解析的。
由於cheerio
模組實作了大部分的jquery
的函數,因此,本文在這裡不進行過多的介紹。
透過上面的分析,我們可以看到我們的資料來源不是json
,而是html
,對jquery
來說,html
應該在發送ajax
請求的時候,設定dataType
為text
。
主要流程(jquery):
1. 利用ajax請求,傳入url和設定dataType
2. 利用$(data)
將ajax
所得的資料轉換成jquery
物件。
3. 利用jquery
的find
和get
方法,找出需要取得的元素。
4. 利用jquery
的attr
和html
方法,取得所需的資訊。
5. 將上述資訊整合成json字串或之前對你的html
進行dom
操作,完成資料的載入。
主要流程(nodejs):
1. 利用requets請求,傳入url和設定dataType
2. 利用cheerio.load(body)
將request
得到的資料轉換成cheerio
物件。
3. 利用cheerio
的find
和get
方法,找到需要取得的元素。
4. 利用cheerio
的attr
和text
方法,取得所需的資訊。
5. 將上述資訊整合成json字串,利用express
的res.json
將json回應給客戶端(小程式或其他APP)。
var express = require('express');var router = express.Router();var bodyParser = require("body-parser");var http = require('http');const cheerio = require('cheerio');/* GET home page. */router.get('/', function (req, res, next) { res.render('index', {title: 'Express'}); });/* GET 妹子图列表 page. */router.get('/parser', function (req, res, next) { var json =new Array(); var url = `http://m.mmjpg.com/getmore.php?te=0&page=3`; var request = require('request'); request(url, function (error, response, body) { if (!error && response.statusCode == 200) { var $ = cheerio.load( body );//将响应的html转换成cheerio对象 var $lis = $('li');//便利列表页的所有的li标签,每个li标签对应的是一条信息 var json = new Array();//需要返回的json数组 var index = 0; $lis.each(function () { var h2 = $(this).find("h2");//获取h2标签,方便获取h2标签里的a标签 var a = $(h2).find("a");//获取a标签,是为了得到href和标题 var img = $(this).find("img");//获取预览图 var info =$($($(this).find(".info")).find("span")).get(0);//获取发布时间 var like = $(this).find(".like");//获取点赞次数 //生成json数组 json[index] = new Array({"title":$(a).text(),"href":$(a).attr("href"),"image":$(img).attr("data-img"),"timer":$(info).text(),"like":$(like).text()}); index++; }) //设置响应头 res.header("contentType", "application/json"); //返回json数据 res.json(json); } }); }) ;/** * 从第(1/50)张这样的字符串中提取50出来 * @param $str * @returns {string} */function getNumberFromString($str) { var start = $str.indexOf("/"); var end = $str.indexOf(")"); return $str.substring(start+1,end); }/* GET 妹子图所有图片 page. */router.get('/details', function (req, res, next) { var json; var url = `http://m.mmjpg.com/mm/958`; var request = require('request'); request(url, function (error, response, body) { if (!error && response.statusCode == 200) { var $ = cheerio.load( body );//将响应的html转换成cheerio对象 var json = new Array();//需要返回的json数组 var index = 0; var img = $($(".content").find("a")).find("img");//每一次操作之后得到的对象都用转换成cheerio对象的 var imgSrc = $(img).attr("src");//获取第一张图片的地址 var title = $(img).attr("alt");//获取图片集的标题 var total =$($(".contentpage").find("span").get(1)).text();//获取‘第(1/50)张’ total = getNumberFromString(total);//从例如`第(1/50)张`提取出50来 var imgPre = imgSrc.substring(0,imgSrc.lastIndexOf("/")+1);//获取图片的地址的前缀 var imgFix = imgSrc.substring(imgSrc.lastIndexOf("."));//获取图片的格式后缀名 console.log(imgPre + "\t" + imgFix); //生成json数组 var images= new Array(); for(var i=1;i<=total;i++) { images[i-1] =imgPre+i+imgFix; } json = new Array({"title":title,"images":images}); //设置响应头 res.header("contentType", "application/json"); //返回json数据 res.json(json); } }); }) ; module.exports = router;
在瀏覽中,取得清單頁的json,截圖如下:
#詳情頁的json獲取,截圖如下:
#上面的json經過格式檢驗,都是有效的。
//获取妹子图的列表function loadData() { url = 'http://m.mmjpg.com/getmore.php'; $.ajax({ url: tmpurl, method: 'get', dataType: "application/text", data:{ te:0, page:3 }, success: function (data) { if (data) { ret = "<ul>" + ret + "</ul>"; var lis = $(ret).find("li"); var one = ''; $(lis).each(function () { var a = $(this).find("h2 a"); var ahtml = $(a).html();//标题 var ahref = $(a).attr('href');//链接 var info = $(this).find(".info"); var date = $($(info).find("span").get(0)).html(); var like = $($(info).find(".like")).html(); var img = $(this).find("img").get(0); var imgsrc = $(img).attr('data-img'); //接下来,决定如何对数据进行显示咯。如dom操作,直接显示。 }); } else { alert("数据加载失败,请重试"); } } }); };//end of loadData//图片详情页的获取,就不再提供jquery版本的代码了
本文主要解决了:1.jquery解析请求过来的html如何实现的问题;2.nodejs环境下jquery重度使用者的替代函数库的问题;3.nodejs下,如何发送ajax请求的问题(ajax请求,本身就是一个request请求);4. 本文用实际的案例来介绍了如何使用cheerio
进行dom操作。
【相关推荐】
1. HTML免费视频教程
以上是教你怎麼在nodejs下解析html的詳細內容。更多資訊請關注PHP中文網其他相關文章!