文章目录
- Intro
- QA
- DOMParser 在 console 的使用
- cheerio 在 node 项目中的使用
- Reference
- 测试
- sum
Intro
有一天我在写爬虫。
其实也说不上是爬虫,就是打开浏览器上网,觉得页面有些数据挺有意思,就打开开发者工具,在 Network/Console 中通过 javascript 原生的 fetch 方法 批量、自动地请求一些web资源。
其中有一个关节,是以下的需求:
有一些字符串格式的HTML源码,需要将其转换为 document 对象(DOM对象),
这样我就可以在 console 直接使用选择器(selector)对该HTML文档的文本内容进行过滤清洗处理。
QA
问题来了,如何将 字符串格式的HTML源码
转化为 document类型的DOM对象
?
答案分两种情况:
cheerio
- 在 node 编程环境(需要有相关的类库支持)DOMParser
在浏览器控制台(需要有原生 javascript 的 API 支持)
DOMParser 在 console 的使用
MDN DOMParser
https://developer.mozilla.org/zh-CN/docs/Web/API/DOMParser
var stringContainingXMLSource = `<!DOCTYPE html> <html lang="en"> <head> <title>wuyujin1997</title> </head> <body> <div id="wyj"> <h2><a href="https://wuyujin.blog.csdn.net/">wuyujin1997 DOMParser demo</a></h2> </div> </body> </html>`;var parser = new DOMParser();
var doc = parser.parseFromString(stringContainingXMLSource, "text/html");// 这个 doc 对象就是整个HTML文档的 DOM对象
console.log("type: ", Object.prototype.toString.call(doc));
console.log(doc);// document 的 DOM对象 可以开始调用原生API通过选择器对子节点进行操作了。
console.log(doc.querySelector("div#wyj"));
console.log(doc.getElementById("wyj"));
这个 DOMParser 不止可以解析 html,也可以解析 xml。
不同类型下的 mimeType 见下表:
"mimeType"
"text/html"
"text/xml"
"application/xml"
"application/xhtml+xml"
"image/svg+xml"
cheerio 在 node 项目中的使用
https://cheerio.js.org/
https://www.npmjs.com/package/cheerio
var cheerio = require("cheerio");
var htmlSourceString = `<!DOCTYPE html> <html lang="en"> <head> <title>wuyujin1997</title> </head> <body> <div id="wyj"> <h2><a href="https://wuyujin.blog.csdn.net/">wuyujin1997 DOMParser demo</a></h2> </div> </body> </html>`;var cheerioOptions = {xml: {withDomLvl1: true,normalizeWhitespace: false,xmlMode: true,decodeEntities: true,},
};const $ = cheerio.load(htmlSourceString, cheerioOptions);
console.log($.html());
console.log($.text());var myDiv = $("div#wyj");
// 用选择器获取的DOM节点对象 也可以调用 .html() .text()
Reference
- MDN fetch
- MDN XMLSerializer
DOMParser 是从字符串格式的HTML源码中解析出一个document类型的DOM对象。
而 XMLSerializer 的作用则正好相反。
当然,有了document 或其他DOM节点,想获取内容,还有 innerText innerHTML outerText outerHTML 等dom对象的成员属性可以使用。
innerHTML, innerText, outerHTML, outerText的区别
- 邱仲麟 明代北京的瘟疫与帝国医疗体系的应变
- 99藏书网 夜谭十记
这个网站对于 network response 中的HTML源码做了一些DOM节点顺序
的技术处理。
测试
邱仲麟 明代北京的瘟疫与帝国医疗体系的应变 https://www.docin.com/p-1077305105.html
打开 F12 Network,然后把网页下拉,可以看到新发送的网络请求:
这样的请求共有58个(就是网页里的页码,上图中可以看到),每个请求就是一张图片:
/*** https://www.docin.com/p-1077305105.html* 邱仲麟 《明代北京的瘟疫与帝国医疗体系的应变》*/function saveStringToFile(filename, blobFile) {// 创建一个 <a> 标签对象var linkTag = window.document.createElement("a");// 设置该实例的 download 和 href 属性(HTML 5 标准属性)linkTag.download = filename;linkTag.href = window.URL.createObjectURL(blobFile);// 把刚才手动创建的 <a> 添加到 DOM 文档中window.document.body.appendChild(linkTag);linkTag.click(); // 调用点击事件// 移除刚才添加的子标签window.document.body.removeChild(linkTag);
}function downloadIt(fileName, url) {fetch(url, {"headers": {"accept": "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8","accept-language": "en-US,en;q=0.9","cache-control": "no-cache","pragma": "no-cache","sec-ch-ua": "\"Chromium\";v=\"106\", \"Google Chrome\";v=\"106\", \"Not;A=Brand\";v=\"99\"","sec-ch-ua-mobile": "?0","sec-ch-ua-platform": "\"Windows\"","sec-fetch-dest": "image","sec-fetch-mode": "no-cors","sec-fetch-site": "same-site"},"referrer": "https://www.docin.com/p-1077305105.html","referrerPolicy": "no-referrer-when-downgrade","body": null,"method": "GET","mode": "cors","credentials": "include"}).then(resp => {return resp.blob();}).then(data => {saveStringToFile(fileName, data);})
}// `https://docimg1.docin.com/docinpic.jsp?file=1077305105&width=892&sid=Sr8*1MVeKYpaCGIMdVwE4mJP4SZgGRO48trgKBhSIIJUUt34nLfam19mfrHxffcH&pageno=19&pcimg=1`;
// `https://docimg1.docin.com/docinpic.jsp?file=1077305105&width=892&sid=Sr8*1MVeKYpaCGIMdVwE4mJP4SZgGRO48trgKBhSIIJUUt34nLfam19mfrHxffcH&pageno=${pageno}&pcimg=1`;for (var i = 1; i <= 58; i++) {var pageno = i;// 这个URL需要随时替换。因为 session 会失效。var url = `https://docimg1.docin.com/docinpic.jsp?file=1077305105&width=892&sid=Sr8*1MVeKYpaCGIMdVwE4mJP4SZgGRO48trgKBhSIIJUUt34nLfam19mfrHxffcH&pageno=${pageno}&pcimg=1`;downloadIt(pageno + ".png", url);
}
结果:
如果有法子把多张图片合并成一个pdf文件就好了。
需求: 多张任意格式的图片-->一个pdf文件
。
有很多网站提供这样的服务,但是要么要注册,要么充钱,要么页面有广告病毒,要么你不会用……
有没有办法自己写程序实现以上的需求?
当然可以。
不然别人的网站是拿什么写的?
搜索javascript Blob File
,自己实现。
sum
最后一句话:
javascript+浏览器+网络,已经可以做很多事了。
但是,要正确使用工具。
学习是学习,不要影响他人的利益。