V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
zhuzhuaini
V2EX  ›  JavaScript

JS 中如何让 String 继承 getElement

  •  
  •   zhuzhuaini · 2021-06-07 21:39:24 +08:00 · 2052 次点击
    这是一个创建于 1025 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前在学习 JS,主要目的是写一个油猴脚本,我的理解是油猴中写的 JS 脚本可以外挂在需要执行的网页当中。

    目前我的需求是,先获取网页当中的 href 超链接(目前已经实现)

    然后通过油猴的“GM_xmlhttpRequest”去访问这个超链接,并返回源码(这一步也已经实现)

    剩下的就是解析源码了,但是我也需要获取源码中的节点嘛,那我本来获取 href 超链接可以使用 document.getElementsByClassName 的方式去获取,但现在返回回来的源码是一个 String 类型的数据,他没法使用类似 getElementsByClassName 的方法去定位,所以我来问问有没有什么方法可以实现让 String 数据继承,如果没有的话,我就要想办法用正则去实现了。。。

    我看了其他人写的代码,基本上都用到了一些库可以解析,比如 request,Cheerio 啥的,但是我琢磨了下发现都似乎无法在油猴上实现导入这些库。

    如果各位大佬有更好的方案也请指教。。

    Rache1
        1
    Rache1  
       2021-06-07 21:50:38 +08:00   ❤️ 2
    var el = document.createElement('div');
    el.innerHTML = <返回的源码字符串>

    然后 el.getElementsByClassName 这些方法就可以用了
    tyx1703
        2
    tyx1703  
       2021-06-07 21:50:48 +08:00   ❤️ 1
    1. 首先利用 `document.createElement` 创建一个顶级节点 el,然后 `el.innerHTML = source`, 最后用 `el.getElementsByClassName`

    2. 利用 jQuery
    iNaru
        3
    iNaru  
       2021-06-07 21:52:21 +08:00   ❤️ 1
    GM_xmlhttpRequest({
    responseType: "document"
    })

    或者使用 DOMParser
    zhuzhuaini
        4
    zhuzhuaini  
    OP
       2021-06-07 22:07:38 +08:00
    @faqqcn 大佬好 前面两步都好了 但是最后用方法的时候会提示 el.getElementById is not a function...
    zhuzhuaini
        5
    zhuzhuaini  
    OP
       2021-06-07 22:13:36 +08:00
    @faqqcn 对了 我返回回来的源码 中文全部变成了 一个黑框框 中间是个问号�� 这种是怎么回事 感觉像是编码问题 但是 GM_xmlhttpRequest 似乎没有给我太多的选择让我去返回编码
    tyx1703
        6
    tyx1703  
       2021-06-07 22:20:23 +08:00   ❤️ 1
    @zhuzhuaini getElementById 只能通过 document 调用,可以用 el.querySelector 代替。
    zhuzhuaini
        7
    zhuzhuaini  
    OP
       2021-06-07 23:06:20 +08:00
    @tyx1703 好的 你知道为什么 GM_xmlhttpRequest 获取回来的源码中文部分是乱码么。。
    muzuiget
        8
    muzuiget  
       2021-06-08 05:53:18 +08:00   ❤️ 1
    用 DOMParser 就行了啊。
    tyx1703
        9
    tyx1703  
       2021-06-08 08:19:36 +08:00 via iPhone   ❤️ 1
    @zhuzhuaini 抱歉,这个不了解
    Rache1
        10
    Rache1  
       2021-06-08 09:17:54 +08:00   ❤️ 1
    @iNaru 😂 牛,学到一个新 API
    duan602728596
        11
    duan602728596  
       2021-06-08 09:22:26 +08:00   ❤️ 1
    原生的选择上面已经说了,用 DOMParser 。
    用库解析的话就可以考虑 jsdom 、cheerio 、linkedom
    Rache1
        12
    Rache1  
       2021-06-08 09:27:22 +08:00   ❤️ 1
    @zhuzhuaini 黑框一般都是中文乱码了,这个可以试着添加 header (Accept-Charset) 来请求服务器发回指定的编码的数据,也可以自行转换编码。
    zhuzhuaini
        13
    zhuzhuaini  
    OP
       2021-06-08 09:32:00 +08:00
    @muzuiget
    @iNaru
    感谢回复,目前题目的问题已经解决了,但是有个新问题,就是获取回来的页面中文是乱码,我研究了下,应该是目标页面采用 GB2312 编码,而 GM_xmlhttpRequest 默认使用了 utf8 的问题导致的,目前我采取了如下方案:
    1:在请求标头中添加 gb2312 。结果无效,输出还是乱码
    2:将获取下来的乱码源码经过函数转换成 UTF-8 。结果无效,输出为 URL 编码形式了,但是我手动 URL 解码后发现还是乱码的。
    以上我想到的两种方案均失败了,,所以来问问大佬有没有可行的方案-。-
    Rhilip
        14
    Rhilip  
       2021-06-08 09:37:54 +08:00   ❤️ 1
    上面说 jsdom 、cheerio 、linkedom 都是瞎说。
    油猴脚本运行环境是浏览器,而不是 Node,所以方法就:
    1. L3 所说的,在 GM_xmlhttpRequest 时直接指定返回类型为 document,让浏览器 xhr 将其直接解析为 Document 最为方便;或是用 DOMParser,这样你可以拿到 string 后做一些修改再解析
    2. L2 所说的,用 jQuery 生成一个对象。我认为 jQuery 在 userscript 中还是很有用的。
    3. L1 所说的,直接创建一个 document.createElement('div') ,然后修改 innerHTML 。但最不建议的也是这种方法,因为 用 GM_xmlhttpRequest 通常拿到的是完整的网页源代码
    zhuzhuaini
        15
    zhuzhuaini  
    OP
       2021-06-08 09:38:44 +08:00
    @faqqcn 尝试了添加 header:
    headers: {
    'Accept': 'text/html; charset=UTF-8',
    },
    其中 UTF-8 和 GB2312 我都试了 均无效,感觉这服务器不听我的 哈哈哈
    zhuzhuaini
        16
    zhuzhuaini  
    OP
       2021-06-08 09:41:11 +08:00
    @Rhilip 感谢回复,是的,楼上几个方案我都试了,最后发现还是 L3 的来的最简单直接
    zhuzhuaini
        17
    zhuzhuaini  
    OP
       2021-06-08 09:43:48 +08:00
    我感觉我的问题和
    https://zhidao.baidu.com/question/16114153.html
    这位老哥的是相似的,只是他的解决方案好像并不适合我
    muzuiget
        18
    muzuiget  
       2021-06-08 09:48:41 +08:00   ❤️ 1
    @zhuzhuaini 中文编码用 TextDecoder 转换一下就行了,不要用 GM_xmlhttpRequest,直接用 fetch 函数,拿到 ArrayBuffer 然后传给 TextDecoder 按 GBK 解码,得到 JS 字符串,然后再用 DOMParser 。
    Rhilip
        19
    Rhilip  
       2021-06-08 11:09:07 +08:00   ❤️ 1
    @muzuiget 应该是涉及到跨域了,所以不能用 fetch,只能用 GM_xmlhttpRequest 。
    其实 GM_xmlhttpRequest 也支持设置 responseType 为 arraybuffer
    Rhilip
        20
    Rhilip  
       2021-06-08 11:24:54 +08:00
    @zhuzhuaini 关于添加请求头这个肯定没用,服务器不响应 utf-8 的就没用。
    有对应测试网址吗?
    因为我感觉如果设置 responseType 为 document,编码这个问题应该是浏览器帮忙解决了的。
    zhuzhuaini
        21
    zhuzhuaini  
    OP
       2021-06-08 11:54:15 +08:00
    @Rhilip 有的 网址是 http://www.dedecms.com/
    我的脚本代码是
    GM_xmlhttpRequest({
    url: 'http://www.dedecms.com/',
    onload: function(res){
    var resp = res.response
    console.log(resp)
    }})
    我目前是测试 所以我随便找了个网页(百度首页),把脚本通过油猴挂载到百度里 ,但是控制台输出的源码就是中文会是乱码
    zhuzhuaini
        22
    zhuzhuaini  
    OP
       2021-06-08 11:56:21 +08:00
    @Rhilip 即时我设置 responseType 为 document 代码如下
    GM_xmlhttpRequest({
    url: '和谐',
    responseType: "document",
    onload: function(res){
    var resp = res.response
    console.log(resp)
    }})
    问题依旧
    duan602728596
        23
    duan602728596  
       2021-06-08 12:40:33 +08:00   ❤️ 1
    其实 jsdom 、cheerio 、linkedom 是可以在浏览器中使用的,只不过没提供浏览器能使用版本而已。
    我现在在浏览器中处理 html 就是用的 DOMparser 和 cheerio (因为 DOMparser 不能在 webworker 的环境中使用)。
    不过看来 LZ 也不一定会用 webpack 和 rollup,还是用 DOMparser 吧。
    Rache1
        24
    Rache1  
       2021-06-08 12:43:29 +08:00   ❤️ 1
    @zhuzhuaini 😂 这个是取决于服务器的实现,服务器没有实现这一块的话,也没办法,只有自己转了
    Rache1
        25
    Rache1  
       2021-06-08 12:45:31 +08:00   ❤️ 1
    @Rhilip 😂 我看文档里面写的是 「 responseType one of arraybuffer, blob, json 」,不过好奇为啥 document 也可以用(没有尝试)
    Rache1
        26
    Rache1  
       2021-06-08 12:46:49 +08:00   ❤️ 1
    @Rhilip 看到了原生 xhr 的 responseType 可以设置 document
    mopig
        27
    mopig  
       2021-06-08 13:15:48 +08:00   ❤️ 1
    加上 overrideMimeType: 'text/html;charset=gb2312' 就行了 😁
    zhuzhuaini
        28
    zhuzhuaini  
    OP
       2021-06-08 13:44:09 +08:00
    @mopig 秒啊! 可以封贴了
    zhuzhuaini
        29
    zhuzhuaini  
    OP
       2021-06-08 13:44:36 +08:00
    感谢楼上的各位帮助 不胜感激!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1201 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 23:12 · PVG 07:12 · LAX 16:12 · JFK 19:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.