JS 中如何让 String 继承 getElement - V2EX
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 2752 次点击
    这是一个创建于 1588 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前在学习 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
    感谢回复,目前题目的问题已经解决了,但是有个新问题,就是获取回来的页面中文是乱码,我研究了下,应该是目标页面采用 编码,而 GM_xmlhttpRequest 默认使用了 utf8 的问题导致的,目前我采取了如下方案:
    1:在请求标头中添加 。结果无效,输出还是乱码
    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 和 我都试了 均无效,感觉这服务器不听我的 哈哈哈
    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=' 就行了
    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     Solana     1364 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 16:43 PVG 00:43 LAX 09:43 JFK 12:43
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86