本文介绍如何在网站中获取别的网站显示的内容(类似于源码)。

本文同时在洛谷和校内OJ发布。


涉及工具

  1. 合适的浏览器。(废话
  2. 支持 <iframe> 标签的浏览器和网页。(主要
  3. 理解 Javascript 与 HTML 的脑子。(可无

对于工具 1,基本所有浏览器都满足。

对于工具 2,基本所有浏览器都满足,但不是每个网页都支持 <iframe>,比如说 luogu.com.cn(与 bilibili 签订了协议),这意味着你不能在该网页上进行爬虫操作。


原理

利用 HTMLIframeElement.contentWindow 获取网页信息。


具体实现步骤

先给出整体代码,再分析。

let ie = document.createElement("iframe");
ie.src = "你的地址";
ie.width = ie.height = 0;
ie.style.position = "fixed";
ie.onload = () => {
	// 处理源码
    ie.contentWindow;
    // ...
    document.body.removeChild(ie);
}
document.body.appendChild(ie);

第一行,不用说了。

第二行,“你的地址”即想获取源码的地址,这个网站可以不支持 <iframe> 标签,但必须支持 <iframe> 引用(本文暂不介绍不支持引用的源码获得)。注意,假设你调用该代码时的网址为 https://some.website.com/114514,则 luogu.com.cn 会被解析为 https://some.website.com/114514/luogu.com.cn,而 https://luogu.com.cn 会被解析为 https://luogu.com.cn

第三行和第四行,为了就是使该 <iframe> 不会被看到(显示)。

第五行起的函数,即处理网页内容。下面列举了几个常用的值(令 iw = ie.contentWindow)。

名称 用途(值)
iw src 网页内的 window 全局变量
iw.document src 网页内的 document 变量
iw.document.body src 网页内的 body 元素
iw.document.head src 网页内的 head 元素

同时,HTMLElement.innerHTML 为该元素内部的 html 源码。

第九行,删除该 <iframe>,删除以减少冗余的内存消耗。

第十一行,运行爬虫。


运行实例

此处理在 Hydro OJ 上运行。

应用

显示题目发表者。(使用 Hydro OJ

let table = document.getElementsByClassName("data-table hide-problem-tag")[1].rows;
for (let i = 0; i < table.length; i++)
{
	let ie = document.createElement("iframe");
	ie.src = table[i].children[3].children[1].href;
	ie.width = ie.height = 0;
	ie.style.position = "fixed";
	ie.onload = () => {
	    let author = ie.contentWindow.document.getElementsByClassName("user-profile-link")[0];
	    author.parentNode.removeChild(author);
	    let li = document.createElement("li");
	    li.className = "problem__tag";
	    li.innerHTML = "<a class=\"problem__tag-link\" href=\"" + author.children[1].href + "\">" + author.children[1].innerText + "</a>";
	    if (table[i].children[3].children[2] == undefined)
	    {
	    	table[i].children[3].appendChild(document.createElement("ul"));
	    	table[i].children[3].children[2].className = "problem__tags";
		}
	    table[i].children[3].children[2].appendChild(li);
	    console.log(i);
	}
	document.body.appendChild(ie);
}

实测,速度较慢。