【问题标题】:How to get only the HTML that interests me on the page?如何在页面上只获取我感兴趣的 HTML?
【发布时间】:2020-01-10 19:16:47
【问题描述】:

各位,我正在为我的表演编辑一个音乐网站的设计。为此,我制作了一个小脚本来放入 Tampermonkey。

不知何故,我只需要获取歌曲名称、作者和所有段落。我该怎么做?

示例歌曲:Lyrics.

<script>
window.onload = () => {
    // Removal of page elements
    document.getElementsByClassName("main-header g-mb")[0].remove(); // Header
    document.querySelector('#breadcrumb').remove(); // Index
    document.querySelector('.cnt-space-top').remove(); // Advertising
    document.querySelector(".cnt-head > a").remove(); // Artist Image
    document.querySelector('.cnt-info_exib').remove(); // Info above the video
    document.querySelector('.cnt-info').remove(); // Info above the video
    document.querySelector('.letra-menu').remove(); // Letter-side info
    document.querySelector('.pl_media').remove(); // Music video
    document.querySelector('.letra-info').remove(); // Info under the letter
    document.querySelector('.letra-share').remove(); // Info under the letter
    document.querySelector('#comments').remove(); // Comments Section
    document.querySelector('#cnt_footer').remove(); // Most Listened Section
    document.getElementsByClassName("g-1")[1].remove(); // Music Footer
    document.getElementsByClassName("g-1")[2].remove(); // Music Footer

    let headerMusic = document.querySelector(".cnt-head"); // Music header
    //headerMusic.style.padding = "0px";
    headerMusic.style.margin = "auto"; // Letter margin
    headerMusic.style.position = "relative";

    let nameMusic = document.querySelector("h1"); // Name of the song
    nameMusic.style.fontSize = "45px";
    nameMusic.style.fontWeight = "bold";

    let artistMusic = document.querySelector("h2 > a"); // Music artist
    artistMusic.style.padding = "0px";
    artistMusic.style.fontSize = "30px";
    artistMusic.style.fontWeight = "bold";

    let letterMusic = document.querySelector('.cnt-letra'); // Lyrics
    letterMusic.style.padding = "0px";
    letterMusic.style.fontSize = "40px";
    letterMusic.style.fontWeight = "bold";

    let allBody = document.querySelector('body');
    allBody.style.textAlign = "center"; // Leave letter centered
    allBody.style.margin = "0px 100px"; // Letter margin
</script>

【问题讨论】:

  • 您在尝试这样做时遇到了什么问题?
  • 像这样只保留歌词不是更容易(开始)吗?但是这样它会在 document.body.innerHTML = document.getElementsByTagName("P")[0].parentElement.innerHTML 之后重建页面并得到一些 JS 错误

标签: javascript html css tampermonkey


【解决方案1】:

如果您的 IE >=9 与 DOMParser 兼容,您可以像这样简单地读取和解析页面。
在 Chrome 和 FF 中,你最终会遇到 CORS 问题。 但是同样的逻辑也可以用在猴子身上——歌曲名称在 2 个 H1 标签中的 1 个中,乐队名称在第一个 H2 中,歌曲在 P 标签块内,周围有一个 DIV。 或者在 node.js 中,您也可以采用类似的方式进行操作,而不会出现 CORS 问题,包括文件访问等。

<script>
loadPage("https://www.letras.mus.br/queen/64295/");
function loadPage(url) {
    var http = new XMLHttpRequest();
    http.open('GET', url, true);
    http.onloadend = function () {
        var html = new DOMParser().parseFromString(this.responseText, "text/html")
        html = html.documentElement;
        var el = html.getElementsByTagName("H1");
        var interesting = el[el.length-1].outerHTML + "\n";
        el = html.getElementsByTagName("H2")[0];
        el.innerHTML = el.innerText;
        interesting += el.outerHTML  + "\n";
        interesting += html.getElementsByTagName("P")[0].parentElement.innerHTML
        document.write(
    "<style>\nbody { background-color:transparent; font-family:Arial, sans-serif; font-size:19px; opacity:1; word-wrap:break-word; margin:0px; }\n" +
    "h1 { color: rgb(255, 102, 0); font-size: 25px; font-weight: 700; letter-spacing: -1px; margin:0px; }\n" +
    "h2,a { color:rgb(183, 183, 0); font-size: 19px; font-weight: 700; letter-spacing: -1px; text-decoration: none; margin:0px; }\n" +
    "p { color: rgb(68, 68, 68); font-weight: 400; line-height: 30.4px; margin-bottom: 30.4px; }\n</style>\n"
        + interesting);
        document.close();
    }

    http.send();
}
</script>

这里 node.js 版本将您要查找的内容保存到文件中:

const request = require('request');
const jsdom = require("jsdom");
var fs = require('fs');

loader("https://www.letras.mus.br/queen/64295/");

function processDOM(body) {
    var dom = new jsdom.JSDOM(body);
    var html = dom.window.document;
    // Song name
    var el = html.querySelectorAll("H1");
    el = el[el.length - 1];
    var items = [el.textContent];
    var interesting = "<style>\nbody { background-color:transparent; font-family:Arial, sans-serif; font-size:19px; opacity:1; word-wrap:break-word; margin:0px; }\n" +
    "h1 { color: rgb(255, 102, 0); font-size: 25px; font-weight: 700; letter-spacing: -1px; margin:0px; }\n" +
    "h2,a { color:rgb(183, 183, 0); font-size: 19px; font-weight: 700; letter-spacing: -1px; text-decoration: none; margin:0px; }\n" +
    "p { color: rgb(68, 68, 68); font-weight: 400; line-height: 30.4px; margin-bottom: 30.4px; }\n</style>\n" +
    el.outerHTML + "\n";
    // Band
    el = html.querySelector("H2");
    items.push(el.textContent.trim());
    el.innerHTML = items[1];
    interesting += el.outerHTML + "\n";
    // Lyrics
    el = html.querySelector("P").parentElement.innerHTML;
    interesting += el.replace(/<br>/g, '<br>\n').replace(/<\/p>/g, '</p>\n');
    items.push(interesting);
    return items;
}

// Based on https://stackoverflow.com/questions/38428027/why-await-is-not-working-for-node-request-module#38428075
async function loader(url) {
    var res = await doRequest(url);
    // Save new simple page
    var pageName = res[0].replace(/\s/g, '_') + ".htm"; // song_name.htm
    fs.writeFile(pageName, res[2], function (err) { // html data
        if (err) throw err;
        console.log(pageName + ' saved.');
    });
}

function doRequest(url) {
    return new Promise(function (resolve, reject) {
        request(url, function (error, res, body) {
            if (!error && res.statusCode == 200) {
                resolve(processDOM(body));
            } else {
                reject(error);
            }
        });
    });
}

小糖 - 元素计算样式打印机 - 它会创建空元素,获取您的计算样式并打印不同的值。

var el=prompt('Element:',"body"), defaultStyles, computedStyles;
defaultStyles = getStyles({}, window.getComputedStyle(document.createElement(el)));
computedStyles = el + ' ' + JSON.stringify(getStyles(defaultStyles, window.getComputedStyle(document.querySelector(el))), null, 3)
.replace(/\"([^\"]+)\": \"([^\"]+)\",/g,"$1: $2;").replace(/\n/g, "\r\n");
function getStyles(defaultStyles, computedStyles) {
    var content = {};
    for (var i=0; i<computedStyles.length; i++) {
        cssProperty = computedStyles[i];
        cssValue = computedStyles.getPropertyValue(cssProperty);
        if(defaultStyles[cssProperty] != cssValue)
            content[cssProperty] = cssValue;
    }
    return content;
}
console.log(computedStyles)
//prompt('Styles: ', computedStyles);

prompt("Copy bookmarklet:", 'javascript:var el=prompt("Element:","body"), defaultStyles, computedStyles;defaultStyles = getStyles({}, window.getComputedStyle(document.createElement(el)));computedStyles = el + " " + JSON.stringify(getStyles(defaultStyles, window.getComputedStyle(document.querySelector(el))), null, 3).replace(/\\"([^\\"]+)\\": \\"([^\\"]+)\\",/g,"$1: $2;").replace(/\\n/g, "\\r\\n");function getStyles(defaultStyles, computedStyles) {var content = {};for (var i=0; i&lt;computedStyles.length; i++) {cssProperty = computedStyles[i];cssValue = computedStyles.getPropertyValue(cssProperty);if(defaultStyles[cssProperty] != cssValue)content[cssProperty] = cssValue;}return content;}prompt("Styles: ", computedStyles),undefined')

【讨论】:

  • 所以我的要求不完全是这样,我会更新这个问题以试图说清楚。关于您的回答,我真的很喜欢第一个代码,它对我有很大帮助,但是我可以更改此脚本的第一行 (loadPage ("https://www.letras.mus.br/queen/64295/");) 以适用于该站点上的所有一般音乐?已经是这个版本的node.js了,我不是很懂,还不是很了解,不过非常感谢大家的解答。
  • 当然,这是一个通用功能,你可以把任何像这个例子那样组织页面的 URL 放在这里,它会起作用。 Node.js 是单独安装的,它可以运行 JavaScript 客户端或服务器应用程序而不受 CORS 等限制(如果它们不在服务器端)。所以第一个版本只有 IE,第二个版本如果你安装了 node.js 并请求,jsdom 和 fs 包,它可以在任何地方工作,包括 linux。喜欢的话可以采纳答案。
  • 想知道如何收集所有链接,但并非不可能 - 如果您指出从哪里开始,我可以尝试获取该功能的列表;-) 如果您不知道如何做吧……
  • 但是如何自动输入歌曲的网址呢?我还不明白。
  • var 歌曲 = [url1, url2, ...]; for(歌曲中的var s)加载程序(歌曲[s]);会很容易,但是假设您只有一些带有链接的页面,那将需要更多的努力......
猜你喜欢
  • 2010-11-03
  • 1970-01-01
  • 2018-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-10
  • 1970-01-01
  • 2011-08-10
相关资源
最近更新 更多