打开Python爬虫实战练习页面网页滚动加载的原理及爬取(JavaScript加密混淆逆向基础)_H03_Spiderbuf,可以看到页面内容是豆瓣电影评分,而且往下滚动页面会有几次内容的加载,到了《哈利·波特与魔法石》这里停了下来。
这种情况通常都是由JavaScript代码控制的,通过计算页面内容的高度及位置等判断是否需要加载新的数据。
在网页上点击右键 > 显示网页源代码,可以看到一部分的豆瓣电影评分内容,比我们在页面上看到的内容要少很多。这是因为浏览器查看源码这里通常只能查看到到首次加载的HTML代码,而通过JavaScript代码生成的HTML内容并不会在这里显示出来。想要看到完整的内容,就需要到开发者工具 -> Elements(元素)那里查看。
F12打开谷歌浏览器开发者工具,刷新一下页面,切换到开发者工具Network标签页,可以看到除了加载了h03页面之外,还有一个CSS样式文件以及一些jpg图片,这些图片点击一下就能看到其实就是一些电影海报,还有一个i7KQc.js的js文件,还有一个请求显示显示了5f685274073b这样的。
我们点开5f685274073b这个请求,右边展开的详情页点击Response(响应),就能看到里面是一些HTML代码内容,主要由一些div之类的组成。大致检查一下这些代码,就会在最后发现一个隐藏的div。
<div id="sLaOuol2SM0iFj4d" hidden>279fcd874c72</div>
做爬虫的时候要特别留意这些隐藏的东西,因为隐藏的东西往往就是做爬虫的关键信息。
到了这里还无法形成我们做这个爬虫的思路,但结合上面的分析,我们知道有通过JavaScript代码加载的内容,而我们目前看到的JavaScript代码就只有i7KQc.js这个文件。
点开之后发现是明文,而且逻辑也不复杂,稍微懂一些JavaScript语言的都能看懂。
window.addEventListener('scroll', function () {
const pageHeight = document.body.scrollHeight;
const windowHeight = window.innerHeight;
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
const threshold = 100;
if (pageHeight - (windowHeight + scrollTop) < threshold) {
var page = document.getElementById('sLaOuol2SM0iFj4d');
if (page == null) {
return;
}
fetch("./h03/" + page.textContent).then(response => response.text())
.then(function (data) {
var main_div = document.getElementById('main');
page.remove();
main_div.insertAdjacentHTML("beforeEnd", data);
});
}
});
这些JavaScript代码就是给网页加入了一个滚动事件监听,在页面滚动里计算是否滚动到了底部,如果是,则通过getElementById获取元素ID为sLaOuol2SM0iFj4d的元素。我们回到网页源码查找,可以看到这个元素是一个div。
<!-- HTML源码第240行 -->
<div id="sLaOuol2SM0iFj4d" hidden>5f685274073b</div>
然后通过fetch函数向后台请求数据,URL带上ID为sLaOuol2SM0iFj4d的div的内容。然后把这个元素删除,再把后台返回的内容插入到main元素的最后面。
结合我们在上面发现的隐藏元素,ID同样为sLaOuol2SM0iFj4d,而且在网页滚动至不再加载新的内容的时候,最后返回的内容没有了这个隐藏元素。这样综合分析,就能得出这个网页的加载思路了:
以ID为sLaOuol2SM0iFj4d的div内容作为参数,向后台请求新的数据,直至到返回的数据没有新的参数,说明已经全部加载完毕。
这个思路是不是很熟悉,其实有点像我们之前的E03 - 无序号翻页无序号翻页。只不过这次返回的不一定是一个完整的页面。
分析出了这个网页内容的加载逻辑,我们就可以使用Python写爬虫代码了。
url = 'http://www.spiderbuf.cn/h03/'
html = requests.get(url, headers=myheaders).text
# get next page uri
uri = ''
root = etree.HTML(html)
divs = root.xpath('//div[@id="sLaOuol2SM0iFj4d"]/text()')
if len(divs) > 0:
uri = divs[0]
i = 1
while (uri != '') & (i < 10):
html = requests.get(url, headers=myheaders).text
uri = '' # ***
root = etree.HTML(html)
divs = root.xpath('//div[@id="sLaOuol2SM0iFj4d"]/text()')
if len(divs) > 0:
uri = divs[0]
i += 1
把数据都爬了下来,接下来根据之前的xpath知识对这个网页进行解析提取内容即可。
完整示例代码:示例代码