找回密码
 立即注册
搜索
查看: 1981|回复: 20

[软件] 怎么用JS脚本获取链接内的元素?

[复制链接]
     
发表于 2021-8-30 16:14 | 显示全部楼层 |阅读模式
如图, 这是一张qq相册网页的截图

我想统计所有上传者, 但这个页面上没有相关信息
但是点进去之后可以看到上传者的qq名

我想问下有没有什么手段可以用JS脚本直接获取到这个名字...
我JS太菜了 一时想不出来方法

还是说我应该用python爬虫?
我虽然没用过python爬虫 但是好像很强大?

回复

使用道具 举报

     
发表于 2021-8-30 16:43 | 显示全部楼层
用什么编程语言都行
如果是在浏览器里跑 JS, 那么肯定得学习浏览器的 DOM API
在页面上选择元素用 querySelectorAll
取元素的文本内容用 innerText
具体的 API 文档推荐 MDN https://developer.mozilla.org/en ... nt/querySelectorAll

不知道现在有推荐什么 JS 教材
早年自己读过的书是这个 https://book.douban.com/subject/3007076/
回复

使用道具 举报

     
发表于 2021-8-30 16:51 来自手机 | 显示全部楼层
这个得从http协议学起了

—— 来自 Xiaomi Redmi K30 5G, Android 11上的 S1Next-鹅版 v2.4.4.1
回复

使用道具 举报

     
 楼主| 发表于 2021-8-30 16:53 | 显示全部楼层
5long 发表于 2021-8-30 16:43
用什么编程语言都行
如果是在浏览器里跑 JS, 那么肯定得学习浏览器的 DOM API
在页面上选择元素用 querySel ...

基础的DOM我会(吗)
但不是很会

他上一级的页面有相关的信息 我用遍历xpath储存下来了
但到了这一级就没有可以直接获取的信息了
需要点个链接进入下一个frame(是这么说的吗? 这个概念我用的对吗?)
才有信息

就是这个怎么处理我没太懂
回复

使用道具 举报

     
发表于 2021-8-30 16:54 | 显示全部楼层
点了之后是重新请求了新页面还是在原页面里面?
还在原页面的话先模拟点击:https://stackoverflow.com/questi ... ick-with-javascript
回复

使用道具 举报

     
 楼主| 发表于 2021-8-30 16:54 | 显示全部楼层
凶手 发表于 2021-8-30 16:54
点了之后是重新请求了新页面还是在原页面里面?
还在原页面的话先模拟点击:https://stackoverflow.com/que ...

原页面 我看看这个
回复

使用道具 举报

     
发表于 2021-8-30 16:55 | 显示全部楼层

先模拟点击 然后lz你需要的内容就可以用dom api弄出来了吧

评分

参与人数 1战斗力 +1 收起 理由
冰箱研会长e-3M + 1

查看全部评分

回复

使用道具 举报

     
发表于 2021-8-30 16:59 | 显示全部楼层
冰箱研会长e-3M 发表于 2021-8-30 16:53
基础的DOM我会(吗)
但不是很会

my bad, 没看清主楼是要点击链接, 然后去拿新页面的数据
如果能拿到链接的 href 的话应该可以用 `window.open()`
用新开 window 的 .document 去访问新窗口里的 DOM
再就是可以考虑用 https://github.com/puppeteer/puppeteer 这种真-浏览器爬虫

评分

参与人数 2战斗力 +2 收起 理由
凶手 + 1 puppeteer 就是起了一个 headless chromium.
冰箱研会长e-3M + 1 着什么神物

查看全部评分

回复

使用道具 举报

     
 楼主| 发表于 2021-8-30 17:00 | 显示全部楼层
凶手 发表于 2021-8-30 16:55
先模拟点击 然后lz你需要的内容就可以用dom api弄出来了吧

试了一下 基本差不多了 这个思路可以
稍微加几个sleep等待自动运行就行了
回复

使用道具 举报

     
 楼主| 发表于 2021-8-30 17:46 | 显示全部楼层
凶手 发表于 2021-8-30 16:55
先模拟点击 然后lz你需要的内容就可以用dom api弄出来了吧

打开新页面之后没法用xpath定位到元素 返回为null
但在js console直接获取就可以...
试着sleep了一下也获取不到... 感觉是我哪里搞错了?  Xpath没更新?
但我用document.querySelector(".js-report-click[data-tag='nickname']").innerText试了一下也是如此...
我是不是缺少了什么常识性的东西...



  1. function getElementByXpath(path) {
  2.     return document.evaluate(path, document, null,
  3.         XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  4. }
  5. //Function to get XPath

  6. function sleep(milliseconds) {
  7.     var start = new Date().getTime();
  8.     for (var i = 0; i < 1e7; i++) {
  9.       if ((new Date().getTime() - start) > milliseconds){
  10.         break;
  11.       }
  12.     }
  13.   }

  14. function Reture2TopPage(){
  15.     getElementByXpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[1]/a[1]").click();
  16. }

  17. function OpenImagePage(NameCounter){
  18.     getElementByXpath(`//li[${NameCounter}]//div[1]//div[2]//div[1]//a[1]//img[1]`).click();
  19. }

  20. var PicCounter = 1;
  21. var NameList = new Array();

  22. while (getElementByXpath(`//li[${PicCounter}]//div[1]//div[2]//div[1]//a[1]//img[1]`)) {
  23.     OpenImagePage(PicCounter);
  24. var UploaderName = getElementByXpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[4]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/p[1]/a[1]").innerText;
  25.     NameList.push(UploaderName);
  26.     console.log(`Current Title is : `,UploaderName);
  27.     PicCounter=PicCounter+1;
  28.     Reture2TopPage();
  29.     sleep(1200);
  30. }
  31. console.log(NameList.join("\n"))
复制代码

回复

使用道具 举报

     
发表于 2021-8-30 17:50 | 显示全部楼层
冰箱研会长e-3M 发表于 2021-8-30 17:46
打开新页面之后没法用xpath定位到元素 返回为null
但在js console直接获取就可以...
试着sleep了 ...

为嘛非要用xpath
用的话先试一试 http://xpather.com/  
回复

使用道具 举报

     
 楼主| 发表于 2021-8-30 17:57 | 显示全部楼层
凶手 发表于 2021-8-30 17:50
为嘛非要用xpath
用的话先试一试 http://xpather.com/

document.getElementsByClassName也不成
是不是脚本没应用上页面的变化呢..
回复

使用道具 举报

     
发表于 2021-8-30 18:02 | 显示全部楼层
JS 是个单线程运行环境, JS 在执行中的时候浏览器是不会渲染页面的(至少早年我学到的是这样, 我已经不写前端很久了)
OpenImagePage() 调用之后会立即返回, 此时页面的内容根本没变. 所以怎么都取不到
所以要把 sleep 加在 OpenImagePage() 的调用之后, 取文本内容之前.

不过话说回来, 同样因为 "JS 是个单线程运行环境", 你这个 busy waiting 式的 sleep() 实现应该会卡住页面. 这也是个问题.
正确的做法是用 setTimeout() 异步地等待
回复

使用道具 举报

     
发表于 2021-8-30 18:47 | 显示全部楼层
5long 发表于 2021-8-30 18:02
JS 是个单线程运行环境, JS 在执行中的时候浏览器是不会渲染页面的(至少早年我学到的是这样, 我已经不写前 ...

稍微看了下 lz 的问题在于
列表是在一个 iframe 里面
然后那个有作者名字的反而是在外面 所以 devtools 的 js context 要是 top 的话就模拟不了列表元素的点击 要是 app_canvas_frame 的话就无法得到作者的名字
回复

使用道具 举报

     
发表于 2021-8-30 18:52 | 显示全部楼层
冰箱研会长e-3M 发表于 2021-8-30 17:57
document.getElementsByClassName也不成
是不是脚本没应用上页面的变化呢..

js context 是 top 的情况下:
document.getElementById("tphoto").contentDocument.getElementsByClassName("j-pl-photoitem-img")[0].click(); const timer = setTimeout(() => { clearTimeout(timer); console.log(document.querySelector("[data-tag='nickname'").innerText); }, 2500)

lz你可以试试 ok的话照这个思路弄
回复

使用道具 举报

     
发表于 2021-8-30 22:41 | 显示全部楼层
可能你需要了解一下xmlhttpRequest
回复

使用道具 举报

     
发表于 2021-8-30 23:29 | 显示全部楼层
楼主会啥语言?基本都不会的话不建议楼主从0开始学爬虫,要学的东西多而且还要面对各种反爬虫,学习曲线有点陡峭。

我没用过qq相册不清楚有无反爬。
回复

使用道具 举报

     
发表于 2021-8-30 23:57 | 显示全部楼层
本帖最后由 Aeroblast 于 2021-8-31 00:37 编辑

之前想过抓自己的空间留个档,结果做了一半不了了之了。我这有个其他思路,你看看行不行。
一边模拟点击,一边抓请求。
比如我看到一个user.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/cgi_floatview_photo_list_v2后面一串参数,内容是json,里面有个photos列表,一个个什么谁发的 上传时间 图片链接(不知道是不是原图)都有。当然这个api不一定行,可能需要找别的,然后还要查重什么的。

js抓这种请求的话,给XMLHttpRequest.prototype.open和send套一层你的抓取。然后qq空间这堆请求返回不是纯json,外面套个函数,什么什么callback,你可以照着写个函数,eval一下在油猴的作用域就调用你自己的这个函数,直接拿到对象。
  1.     function viewer_Callback(data){
  2.         console.log(data.data.photos)
  3.     }
  4.     XMLHttpRequest.prototype.openO=XMLHttpRequest.prototype.open;
  5.     XMLHttpRequest.prototype.open=function(method, url, async, user, password){
  6.         this.openO(method, url, async, user, password);
  7.         this.url=url;
  8.     }
  9.     XMLHttpRequest.prototype.sendO=XMLHttpRequest.prototype.send;
  10.     XMLHttpRequest.prototype.send=function(para){
  11.         this.sendO(para);
  12.         if(this.url.startsWith("https://user.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/cgi_floatview_photo_list_v2")){
  13.             let onloadO=this.onload;
  14.             this.onload=function(){
  15.                 eval(this.responseText);//调用viewer_Callback
  16.                 onloadO()
  17.             }
  18.         }
  19.     }
复制代码

然后你加上模拟点击下一张,遇到一次请求是19个,photos是个数组里面啥也有

评分

参与人数 1战斗力 +1 收起 理由
冰箱研会长e-3M + 1

查看全部评分

回复

使用道具 举报

     
 楼主| 发表于 2021-8-31 07:23 | 显示全部楼层
糊状物 发表于 2021-8-30 23:29
楼主会啥语言?基本都不会的话不建议楼主从0开始学爬虫,要学的东西多而且还要面对各种反爬虫,学习曲线有 ...

也算是个程序员 但前端啊 浏览器什么的 算是我知识盲区吧
只明白一些轮廓 所以就像这样 具体执行中会遇到很多问题
回复

使用道具 举报

     
发表于 2021-8-31 08:58 来自手机 | 显示全部楼层
冰箱研会长e-3M 发表于 2021-8-31 07:23
也算是个程序员 但前端啊 浏览器什么的 算是我知识盲区吧
只明白一些轮廓 所以就像这样 具体执行中会遇到 ...

Python或者java比较熟可以用selenium+webdriver,js的话我只用过puppeteer,只是我是业余玩票的,自己只抓过小说和免费代理,我寻思比直接在浏览器里运行脚本要方便多了吧

—— 来自 Xiaomi MI 8, Android 10上的 S1Next-鹅版 v2.4.4.1
回复

使用道具 举报

发表于 2021-8-31 21:49 | 显示全部楼层
要不用用八爪鱼
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|上海互联网违法和不良信息举报中心|网上有害信息举报专区|962110 反电信诈骗|举报电话 021-62035905|Stage1st ( 沪ICP备13020230号-1|沪公网安备 31010702007642号 )

GMT+8, 2024-11-15 08:49 , Processed in 0.036381 second(s), 6 queries , Gzip On, Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表