当我们使用requests抓取页面的时候,有时候会发现获取的数据和网页中显示的数据不相同,那么我们可以通过查看源代码的方式查看数据是否是通过Ajax动态获取的。Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式、快速动态网页应用的网页开发技术,无需重新加载整个网页的情况下,能够更新部分网页的技术。
Ajax是通过JavaScript实现的,实际上执行了以下代码:
var xmlhttp;
if(window.XMLHttpRequest){
//code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}else {//code for IE6, IE5
xmlhttp=new ActiveXObject("Microsofg.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState==4 && xmlhttp.status==200){
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("POST","/ajax/",true);
xmlhttp.send();
简要说明一下代码:新建XMLHttpRequest对象,然后调用onreadystatechange属性设置监听,之后调用open()和send()方法向服务器发送请求。因为设置了监听,当服务器返回响应后,onreadystatechange对应的方法便会触发,然后在这个方法里解析响应的内容。
当服务器返回响应后,onreadystatechange对应的方法便会触发,然后xmlhttp的responseText属性就可以获取响应内容。返回的内容可能是HTML,也可能是JSON,只需要在JS中进一步处理即可。
JS可以更改网页内容,解析完响应内容后,就可以调用JS来对网页进行下一步处理。这种操作成为DOM操作。
首先,Ajax同样是想服务器发送请求,然后JS在进行网页数据的更改。但是,这个请求时隐秘的,在地址栏是无法看到变化的。我们该怎么去找到这个URL请求呢?
使用开发者工具,在网页中F12或右键——检查即可打开。在Elements选项卡中是网页的源代码(DOM加载完成后的)。这里切换到Network选项卡,刷新网页。发现其中有许多的条目。这些条目就是网页与服务器之间发送请求与接收响应的所有记录。
Ajax有自己的请求类型,xhr,这些条目中Type为xhr的即是Ajax请求。点击请求则可以查看请求的详细信息。
这里以CSDN为例:
1. 打开开发者工具
当我们不断刷新博客的时候,会发现Ajax请求也会一直增加。其中isDjggList条目包含当前增加的所有文章的信息。
5. 点击Headers
在Request Headers下有x-requested-with: XMLHttpRequest,这个就表示当前条目为Ajax请求。同时在最开头,Request URL就表示Ajax请求的具体URL。知道了这些,我们就可以用Python模拟Ajax请求从而达到获取数据的目的了。
1. 分析请求
打开Ajax 的XHR过滤器,选择其中一个请求,分析参数信息。进入详情界面。
这是一个GET请求,请求链接为https://blog.csdn.net/api/articles?type=new&category=home,请求的参数有两个:type、category。观察其他的请求,发现依然相同。
2. 分析响应
查看Preview选项卡
发现其中显示了9个博客内容,点开其中一个。
这里显示了这篇博客所有内容。
3. 实战演练
根据上面得到的信息,有以下代码:
from urllib.parse import urlencode
import requests
url = 'https://blog.csdn.net/api/articles?type=new&category=home'
headers = {
'Host':'blog.csdn.net',
'Referer':'https://blog.csdn.net',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36',
'X-Requested-With':'XMLHttpRequest',
}
r = requests.get(url=url)
print(r.text)
这里显示的是服务器返回的所有信息,之后便可以去提取想要的信息啦。