关于ajax的详细介绍请读者自行百度或者参考http://theodor.top/article/26中的“ajax”一节。
简单的来说,ajax请求返回的是一串组织好的数据。浏览器会在符合条件(js脚本)的情况下发送一系列符合条件的链接,来向服务器请求更新一组数据。服务器发送数据后,浏览器直接在当前页面改写DOM,达到不跳转链接进行更新的目的。
很多网站利用ajax对页面进行美化处理,同时也能节省服务器的带宽。
有时候我们需要在资讯网站上爬取较多信息,而这些信息正常情况下需要用户不断在浏览器界面做出动作(大多数情况下这个动作是下拉滚动条)才能加载。如果使用selenium等无界面浏览器爬取则太耗时间,使用常规爬虫库则无法对爬取下来的html页面做出动作(也就是激活js)。所以我们需要绕过动作,直接对ajax请求进行爬取,达到快速准确获取数据的目的(事实上,ajax请求返回的数据一般都十分易读,因为没有html的干扰,但也不排除存在直接返回一段html的网站,比如百度贴吧)。
本节我们以微博为例。
我们可以用两种方式获取ajax链接:第一种是分析原页面的script文件找到发送ajax请求的代码;第二种是直接通过工具截取网页发送的ajax请求url,分析其规律并仿写。
其中,分析script脚本是十分不推荐采取的方法,因为网站开发者通常会将js脚本写成十分不友好的形式(请想象一堆var abcdefg出现在你面前,js甚至不用声明变量类型)。但在穷途末路或者爬取者本身有兴趣的情况下也不是不能一试。
第二种方法中的工具可以用浏览器自带的开发者工具(F12),当然想用Fiddler等也不是不可以,重要的是结果不是过程。在待爬取页面按下F12键打开开发者工具,然后点击标签“Network”,将浏览的类别调整到“XHR”(XMLHTTPRequest,这是ajax专有的数据格式):
不断下拉滚动条,会发现XHR区域多了很多内容。观察可以得知它们是一系列GET请求,且其请求参数为ajwvr、category、page、lefnav、cursor、rnd。变动的参数为:page,其每次请求+1,推测为请求页数;rnd,可知其为请求发出的时间戳。
json全称JavaScript Object Notation,是一种数据格式。大多数情况下,你可以将json数据看做字典。
浏览器向服务器发送ajax请求后,服务器会返回一组json数据,浏览器根据此json更新页面。在绕过浏览器直接发送ajax请求时,服务器返回的json数据自然也由我们自行解析。
在已经拿到ajax请求的浏览器开发者工具下,双击ajax请求连接,在展开的窗口中选择Response,可以看到微博服务器端返回的json数据:
其具体的json返回形式如下,其中data为其返回的html文本:
{"code":"100000","msg":"","data":" <!--\u699c\u5355\u680f\u4f4d\u7f6e-->\n <div…(略)"}
可知我们需要的数据在data键内,其为html文本段。
import requests
import time
import datetime
page=2
#分析得知ajax请求的page从2开始(因为page1在打开页面的时候就已经加载到文档里)
lefnav=0
category=0
ajwvr=6
cursor=""
#其余的参数,其意义可以忽略
url="https://weibo.com/a/aj/transform/loadingmoreunlogin?"
#通过分析之前浏览器发出的ajax请求,可得知微博使用的时间戳为毫秒级时间戳
def getrnd():
return round(time.time()*1000)
def geturl():
global page #我们要修改page,就要声明为全局变量
page=page+1
return url+"ajwvr="+str(ajwvr)+"&category="+str(category)+"&page"+str(page-1)+"&cursor="+cursor+"&_rnd="+str(getrnd())
response=requests.get(geturl())
print(response.text)
当然,此处的ajax请求采取了GET的方式,但也有采取POST方式并且要求携带cookie的ajax请求。对于这种情况可以采用设置POST字典的方式。在真正的情况中也会有很多猜不出ajax请求参数的情况,这就需要读者因地制宜随机应变了。但ajax请求的精髓已经被我们讲解过了,无论有多少分支,都不过万变不离其宗耳。
是我的一家之见,若有疏漏还请一笑而过。
其实除了ajax,网页上几乎所有的页面都可以通过找到url->分析参数->伪装请求的方式来爬取。比如说搜索框的操作可以通过向搜索框跳转的链接发送请求来模拟,按钮按下可以通过向按钮绑定的链接发送请求来模拟。这是因为互联网的本质是数据与地址的组合,无论它们有多么华丽,终究也不过是一堆数据。发送请求的主动权在我们手上,只要分析手头的数据,可以说没有什么请求是伪装不了的(当然,我是指你本人使用浏览器可以做出的请求)。
AJAX 实例
一个简单的AJAX实例
创建一个简单的XMLHttpRequest,从一个TXT文件中返回数据。
用AJAX加载 XML 文件
创建一个简单的XMLHttpRequest,从一个XML文件中返回数据。
用AJAX进行一次 HEAD 请求
检索资源(文件)的头信息。
用AJAX进行一次指定的 HEAD 请求
检索资源(文件)的指定头信息。
用AJAX从ASP 文件返回数据
当用户在文本框内键入字符时网页如何与Web服务器进行通信
用AJAX从数据库返回数据
用AJAX网页如何获取数据库中的信息
用AJAX从XML 文件返回数据
创建一个XMLHttpRequest从XML文件中检索数据并显示在一个HTML表格中。
用callback函数的AJAX实例
用一个callback函数创建一个XMLHttpRequest,并从一个TXT文件中检索数据。
如您还有不明白的可以在下面与我留言或是与我探讨QQ群308855039,我们一起飞!
)url:
要求为String类型的参数,(默认为当前页地址)发送请求的地址。
2)type:
要求为String类型的参数,请求方式(post或get)默认为get。注意其他http请求方法,例如put和delete也可以使用,但仅部分浏览器支持。
3)timeout:
要求为Number类型的参数,设置请求超时时间(毫秒)。此设置将覆盖$.ajaxSetup()方法的全局设置。
4)async:
要求为Boolean类型的参数,默认设置为true,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为false。
注意,同步请求将锁住浏览器,用户其他操作必须等待请求完成才可以执行。
5)cache:
要求为Boolean类型的参数,默认为true(当dataType为script时,默认为false),设置为false将不会从浏览器缓存中加载请求信息。
6)data:
要求为Object或String类型的参数,发送到服务器的数据。如果已经不是字符串,将自动转换为字符串格式。get请求中将附加在url后。防止这种自动转换,可以查看 processData(防止自动转换)选项。对象必须为key/value格式,例如{foo1:"bar1",foo2:"bar2"}转换为&foo1=bar1&foo2=bar2。如果是数组,JQuery将自动为不同值对应同一个名称。例如{foo:["bar1","bar2"]}转换为&foo=bar1&foo=bar2。
7)dataType:
要求为String类型的参数,预期服务器返回的数据类型。如果不指定,JQuery将自动根据http包mime信息返回responseXML或responseText,并作为回调函数参数传递。可用的类型如下:
● xml:返回XML文档,可用JQuery处理。
● html:返回纯文本HTML信息;包含的script标签会在插入DOM时执行。
● script:返回纯文本JavaScript代码。不会自动缓存结果。除非设置了cache参数。注意在远程请求时(不在同一个域下),所有post请求都将转为get请求。
● json:返回JSON数据。
● jsonp:JSONP格式。使用SONP形式调用函数时,例如myurl?callback=?,JQuery将自动替换后一个“?”为正确的函数名,以执行回调函数。
● text:返回纯文本字符串。
8)beforeSend:
这个参数主要是为了在向服务器发送请求前,执行一些操作。要求为Function类型的参数,发送请求前可以修改XMLHttpRequest对象的函数,例如添加自定义HTTP头。在beforeSend中如果返回false可以取消本次ajax请求。XMLHttpRequest对象是惟一的参数。
function(XMLHttpRequest){
this; //调用本次ajax请求时传递的options参数
}
9)complete:
要求为Function类型的参数,请求完成后调用的回调函数(请求成功或失败时均调用)。参数:XMLHttpRequest对象和一个描述成功请求类型的字符串。
function(XMLHttpRequest, textStatus){
this; //调用本次ajax请求时传递的options参数
}
10)success:
要求为Function类型的参数,请求成功后调用的回调函数,有两个参数。
(1)由服务器返回,并根据dataType参数进行处理后的数据。
(2)描述状态的字符串。
function(data, textStatus){
//data可能是xmlDoc、jsonObj、html、text等等
this; //调用本次ajax请求时传递的options参数
}
11)error:
要求为Function类型的参数,请求失败时被调用的函数。该函数有3个参数,即XMLHttpRequest对象、错误信息、捕获的错误对象(可选)。ajax事件函数如下:
function(XMLHttpRequest, textStatus, errorThrown){
//通常情况下textStatus和errorThrown只有其中一个包含信息
this; //调用本次ajax请求时传递的options参数
}
12)contentType:
要求为String类型的参数,当发送信息至服务器时,内容编码类型默认为"application/x-www-form-urlencoded"。该默认值适合大多数应用场合。
13)dataFilter:
要求为Function类型的参数,给Ajax返回的原始数据进行预处理的函数。提供data和type两个参数。data是Ajax返回的原始数据,type是调用jQuery.ajax时提供的dataType参数。函数返回的值将由jQuery进一步处理。
function(data, type){
//返回处理后的数据
return data;
}
14)dataFilter:
要求为Function类型的参数,给Ajax返回的原始数据进行预处理的函数。提供data和type两个参数。data是Ajax返回的原始数据,type是调用jQuery.ajax时提供的dataType参数。函数返回的值将由jQuery进一步处理。
function(data, type){
//返回处理后的数据
return data;
}
15)global:
要求为Boolean类型的参数,默认为true。表示是否触发全局ajax事件。设置为false将不会触发全局ajax事件,ajaxStart或ajaxStop可用于控制各种ajax事件。
16)ifModified:
要求为Boolean类型的参数,默认为false。仅在服务器数据改变时获取新数据。服务器数据改变判断的依据是Last-Modified头信息。默认值是false,即忽略头信息。
17)jsonp:
要求为String类型的参数,在一个jsonp请求中重写回调函数的名字。该值用来替代在"callback=?"这种GET或POST请求中URL参数里的"callback"部分,例如{jsonp:'onJsonPLoad'}会导致将"onJsonPLoad=?"传给服务器。
18)username:
要求为String类型的参数,用于响应HTTP访问认证请求的用户名。
19)password:
要求为String类型的参数,用于响应HTTP访问认证请求的密码。
20)processData:
要求为Boolean类型的参数,默认为true。默认情况下,发送的数据将被转换为对象(从技术角度来讲并非字符串)以配合默认内容类型"application/x-www-form-urlencoded"。如果要发送DOM树信息或者其他不希望转换的信息,请设置为false。
21)scriptCharset:
要求为String类型的参数,只有当请求时dataType为"jsonp"或者"script",并且type是GET时才会用于强制修改字符集(charset)。通常在本地和远程的内容编码不同时使用。
*请认真填写需求信息,我们会在24小时内与您取得联系。