网页懒加载场景和解决方案
问题引出
懒加载问题是指网页只渲染页面上显示的元素,在屏幕外面的元素无法校验到或获取到信息。下面以聚水潭订单信息获取为例。
一页上有 50 个订单信息,但是网页代码中只有 16 个元素被加载出来,如果继续滚动网页:
后面的元素会被加载出来,但是前面的元素会消失。总是有元素不显示,影响数据的获取。
解决思路
在循环中维护一个列表,记录已经抓取过的行数据,无限循环向下滚动鼠标滚轮并获取当前可见的元素,用这个 index 属性和列表对比判断,如果这个元素的数据已经抓取,跳过。如果已经抓取到的数据数量已经达到 50 条,则停止抓取数据。
如何判断一条数据是否已经被抓取过了呢?
发现网页代码中,数据行元素的 index 属性是唯一确定的,是从 0 到 49 的 50 个数字。验证一下想法:
打印出了当前页面上显示的 6-17 行。
试一下用这种思路是不是能打印出这一页上所有行元素的 index 值。
流程执行逻辑:
获取已打开的聚水潭订单网页对象 -> 新建列表记录列表
用来记录获取过的行的 index 属性 -> 开始无限循环向下滚动,无限循环的退出条件是,记录列表的长度是 50(已经抓取到页面上所有的行元素属性数据)-> 在无限循环中开始循环相似元素,循环获取当前网页上的所有行元素的 index 属性,如果这个属性已经在记录列表
里,继续下一次循环,按相同规则判断页面上下一个行元素;如果这个属性没有在记录列表
中,则打印这个属性,并添加这个属性到列表中 -> 每进行完一次循环当前页面上显示的相似元素,鼠标在网页上向下滚动,并判依据上述条件判断是否到底,如果到底退出整个循环
执行结果:
打印出了 0-49 的当前页面所有行的的属性值且没有重复。
解决方案
下面以这个思路实际抓取一下整页某几个字段的数据。
行元素有可以被唯一确定的属性
指令获取元素对象(web)
配置如下
关于关联父元素,参考网页中通过关联父元素找子元素。
流程执行逻辑:
获取已打开的聚水潭订单网页对象 -> 新建列表记录列表
用来记录获取过的行的 index 属性 -> 新建列表数据列表
用来记录抓取过的数据 -> 开始无限循环向下滚动,无限循环的退出条件是,记录列表的长度是 50(已经抓取到页面上所有的行元素属性数据)-> 在无限循环中开始循环相似元素,循环获取当前网页上的所有行元素的 index 属性,如果这个属性已经在记录列表
里,继续下一次循环,按相同规则判断页面上下一个行元素;如果这个属性没有在记录列表
中,则关联这个父元素获取当前线上订单号和买家帐号+店铺的元素,获取到它们的文本后,追加在列表数据列表
后面 -> 每进行完一次循环当前页面上显示的相似元素,鼠标在网页上向下滚动,依据上述条件判断是否到底,如果到底退出整个循环 -> 将列表数据
写入影刀数据表格区域
流程执行结果:
找不到类似 index 的属性
有些网站的行元素可能不会有像 index 一样可以唯一确定的属性来判断,这种情况考虑用页面上原有的数据作为唯一判断标准,比如订单号,商品编码等。
下面以聚水潭的内部订单号替代 index 作为判断标准在同一界面进行数据抓取。
流程执行逻辑类似,唯一不同的地方是不再获取行元素的 index 而是关联了当前循环到的行元素为父元素去找内部订单号作为判断标准,记录在记录列表中作为判断依据。
不确定当前页面上共有多少数据
有时候不知道当前页面有多少行数据,无法根据记录列表的长度判断无限循环是否需要退出(页面已经到底),这个时候需要考虑其他判断条件。
注意到如果不做判断,无限循环一直进行下去,但即使已经滚动到屏幕底部,记录列表
和数据列表
的长度都不会再变化了,因为我们已经做了判断,记录列表里已经有过记录的数据不会再抓取。所以可以据此判断页面是否已经到底。
在循环中记录上一次记录列表
的长度,在循环完当前页相似元素后的记录列表
的长度对比,如果没有增加,就退出外层无限循环。
其他可能的解决方案
在聚水潭的订单页面打开 F12,有一个 id 叫 _jt_body
的元素,这个元素的 style 属性是 height: 1035px; overflow-x: auto;
,双击这个属性,把 1035px
改成 10000px
,回车。
之前捕获的行元素也可以校验到 50 个元素。
影刀操作方法:
捕获_jt_body
元素:
聚水潭订单页面为例,要设置的属性:height:10000px;overflow-x:auto