淘先锋技术网

首页 1 2 3 4 5 6 7

Ajax 是一种使用 JavaScript 发起异步请求的技术,其通过 XML 与服务后台交换数据,并在不加载整个网页的情况下改变其部分内容
因为 Ajax 灵活、易用,且更具维护性能,在许多现代网站开发中都会被使用

这里介绍怎么使用爬虫来爬取 Ajax 传递的数据

分析网页结构

我们准备爬取一个文娱数据统计的网站:http://www.endata.com.cn/
目标网页是数据榜单中的票房数据,基于年度票房的数据统计,如下图是2020年电影票房数据的统计
目标网页
图中红箭头指向的是用于选择年份的下拉列表

使用开发者模式,定位下拉列表,可以查看该标签的相关属性
在这里插入图片描述
再到网页源码文件中查找这个标签的 id
在这里插入图片描述
在这里面我们看到一个调用 Ajax 请求接口的方法,以及其参数内容

这显然是一个封装好的方法,我们可以到外部引入的脚本中去查看这个方法的具体实现
在这里插入图片描述
显然是来自这个 Common.js,我们打开这个文件,在里面进行关键字查找
在这里插入图片描述
如此,我们得到了 Ajax 请求的目标 urlPOST 的表单格式,其传递数据的形式为 Json

分析网页请求

除了分析网页结构,我们还可以通过分析网页请求信息来提取关键信息

使用开发者模式,打开 Network 标签,改变年份,观察每次年份变更后重新载入数据时浏览器发起的请求信息
在这里插入图片描述
显然,最先是加载该年份总的电影票房数据信息,后面是单独加载某个电影的数据

查看第一个请求包的详细内容
在这里插入图片描述
是我们想要的信息

模拟请求

我们前面前面获取到的信息有:

  1. Ajax 请求的 url 为:http://www.endata.com.cn/API/GetData.ashx
  2. 请求方法为 POST,表单内容为 year 和 MethodName
  3. 传递数据的形式为 Json

我们根据这些信息进行模拟请求,测试其是否可成功获取数据
在这里插入图片描述
测试成功,模拟的 POST 请求可以获取 Json 形式的数据返回
在这里插入图片描述
Json 格式化数据中,我们想要获取的信息在 Data 字段中的 Table 字段,以数组的形式存储

构建爬虫

由此,我们编写爬虫代码

# 电影票房

import requests
import pandas as pd

def get_boxoffices_by_year(url, headers):
	res_data = []
	for year in range(2008, 2021):
		data = {'year': year, 'MethodName': 'BoxOffice_GetYearInfoData'}
		res = requests.post(url, data=data, headers=headers)
		res_data += res.json()['Data']['Table']
	df = pd.DataFrame(res_data)
	df.to_excel('boxoffices_by_year.xlsx')

if __name__ == '__main__':
	url = 'http://www.endata.com.cn/API/GetData.ashx'
	headers = {
		'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36'
	}
	get_boxoffices_by_year(url, headers)

爬取结果:
在这里插入图片描述

追加(2021-01-23)

现在网站对后台返回的数据进行了加密处理,能获取到的都是密文
后台返回数据
前端在处理数据时候也是做了判断,如果不是一个Json字符串,就会调用webInstace.shell()方法进行解密处理
解密处理
解密器
大概猜测他用的是DES加密算法,DES是对称加密算法,加密密钥和解密密钥是同一个,在前端进行解密,要么是后台另外传了密钥过来,要么就是使用了约定的密钥生成方法,这里就不往下探究了(这里应该是对加密算法的js代码使用了混淆,看得头痛)。
既然网站对数据进行了加密,我们直接使用ajax就不能拿到有效的数据了,或许可以等前端渲染之后再拿数据明文,这里也不继续探究了,这篇文章就当看一乐吧。