爬虫学习[5]
原书《Python与爬虫开发:从入门到实战(微课版)》
异步加载与请求头
异步加载
1.AJAX技术介绍
AJAX是Asynchronous JavaScript And XML的首字母缩写,意为异步JavaScript与XML。使用AJAX技术,可以在不刷新网页的情况下更新网页数据。使用AJAX技术的网页,一般会使用HTML编写网页的框架。在打开网页的时候,首先加载的是这个框架。剩下的部分将会在框架加载完成以后再通过JavaScript从后台加载。
如何判断一个网页有没有使用AJAX技术呢?访问示例网站http://exercise.kingname.info/exercise_ajax_1.html
但是查看源代码时,发现并没有这两段话:
像这种网页上面存在的某些文字,在源代码中却不存在的情况,绝大部分都是使用了异步加载技术。
2.JSON介绍与应用
JSON是一种格式化字符串。JSON字符串与Python的字典或者列表非常相似,仅存在一些细微差别。
json可以认为是一种标准化数据,可以使得不同的程序之间方便的进行通信。
JSON的全称是JavaScript Object Notation,是一种轻量级的数据交换格式。网络之间使用HTTP方式传递数据的时候,绝大多数情况下传递的都是字符串。因此,当需要把Python里面的数据发送给网页或者其他编程语言的时候,可以先将Python的数据转化为JSON格式的字符串,然后将字符串传递给其他语言,其他语言再将JSON格式的字符串转换为它自己的数据格式。
Python中处理JSON格式字符串的库,名字为json。为了将这个字典转换为JSON格式的字符串,需要先导入这个库,之后只需要一行代码
import json
a_json=json.dumps(a)
为了让JSON格式的字符串更便于人阅读,可以进行缩进。使用如下代码可为JSON格式的字符串添加4个空格的缩进:
import json
a_json=json.dumps(a,indent=4)
不仅是字典,Python中的列表或者包含字典的列表,也可以转换为JSON格式的字符串。
如果要把JSON格式的字符串转换为Python的字典或者列表,只需要使用一行代码即可:
import json
a_dict=json.loads(a_json)
3.异步GET与POST请求
使用异步加载技术的网站,被加载的内容是不能在源代码中找到的。对于这种情况,应该如何抓取被加载的内容呢?
可以通过浏览器的开发者模式,一般是F12
,我使用的Firefox浏览器,点开"网络"选项
对网页进行刷新
在这里插入图片描述先点击GET请求:
响应就是所返回的信息,再点开请求头:
红框所划定的即为请求的地址。POST请求操作与GET类似。可以使用requests进行模拟,比较简单,就不进行演示了。
4.特殊的异步加载
最常见、最简单的异步加载情况,但并非所有的异步加载都会向后台发送请求。打开网址并使用开发者模式进行监听,发现并没有尝试请求后台的行为。
查看网页源代码:
那么这个页面上的汉字到底是从哪里加载进来的?这种情况称为伪装成异步加载的后端渲染。数据就在源代码里,但却不直接显示出来。注意,源代码最下面的JavaScript代码,其中有一段:'{"code": "\u884c\u52a8\u4ee3\u53f7\uff1a\u5929\u738b\u76d6\u5730\u864e"}'
尝试使用Python去解析,可以得到答案:
import json
import requests
import re
url="http://exercise.kingname.info/exercise_ajax_2.html"
content=requests.get(url).content.decode()
block=re.findall("secret = '(.*?)'",content,re.S)
need=json.loads(block[0])
print(need['code'])
5.多次请求的异步加载
还有一些网页,显示在页面上的内容要经过多次异步请求才能得到。第1个AJAX请求返回的是第2个请求的参数,第2个请求的返回内容又是第3个请求的参数,只有得到了上一个请求里面的有用信息,才能发起下一个请求。
打开异步加载练习页3
分析发现,页面呈现的内容是通过最后一个POST请求提供的,查看之:
发现有两个比较奇怪的值secret1、secret2
可以通过简单的requests验证发现这两个值是不可进行更改的,否则得不到需要的界面。
在这个例子中,secret1和secret2是固定不变的,因此可以人工从Chrome的开发者工具中复制出来使用。而在实际的爬虫开发过程中,类似于secret1和secret2的这种参数在每次请求的时候都不一样,因此不能手动复制。那么遇到这种情况应该如何处理呢?这个时候就需要考虑这两个参数能不能直接从源代码里面找到?如果源代码里面找不到,那是不是从另一个异步的请求中返回的?
查看网页源代码:
<html>
<head>
<title>exercise ajax load</title>
<script> var secret_2 = 'kingname';</script>
</head>
<body>
<div class="content"></div>
</body>
<script src="static/js/jquery-3.2.1.min.js"></script>
<script src="static/js/loaddata_3.js"></script>
</html>
其中secret_2
和secret2
名虽不一样,但是可以看出是一个参数
而secret1
的关键字在源代码中并没有出现,查看GET请求:
发现了与secret1值相同的值。
注意,它的名字变为了“code”,但是从值可以看出这就是secret1。不少网站也会使用这种改名字的方式来迷惑爬虫开发者。
6.基于异步加载的简单登录
网站的登录方式有很多种,其中有一种比较简单的方式,就是使用AJAX发送请求来进行登录。点击网址
按照输入的提示输入后,会有一个弹窗出现。
现在使用开发者模式,输入账号与口令之后:
当单击“登录”按钮时,网页向后台发送了一条请求。这就是使用POST方式的最简单的AJAX请求。
请求头
请求头有什么用
使用计算机网页版外卖网站的读者应该会发现这样一个现象:第一次登录外卖网页的时候会让你选择当前所在的商业圈,一旦选定好之后关闭浏览器再打开,网页就会自动定位到先前选择的商业圈。
与之类似,有些网址,在PC端和手机端打开完全不同,这又是怎么实现的呢?网站怎么知道现在是计算机浏览器还是手机浏览器在访问这个页面呢?网站怎么能记住地理位置呢?
这就要归功于Headers了。Headers称为请求头,浏览器可以将一些信息通过Headers传递给服务器,服务器也可以将一