有些时候,我们下载到的源码跟浏览器开发者工具中看到的不一样,就是因为很多代码都是在使用过程中有 js 后来生成的,页面不会变动的叫静态网页,页面会因 js 而变动的就叫动态网页
本文先讲利用 Ajax 技术的动态网页
Ajax (asynchronous JavaScript and XML):翻译为异步刷新的 JavaScript 和 XML
工作过程:原始的网页并不包含全部数据,当需要更多数据时,将向服务器发送一个Ajax请求,获取数据来渲染在网页上
例子:比如刷微博,当下拉刷新时,就是在向服务器发送Ajax请求来获取更多微博
前景:越来越多的网页使用Ajax请求,是个趋势
既然下载源码得不到想要数据,那要怎么获取呢?其实每次我们下拉刷新页面,服务器就已经通过 Ajax 把数据发送给我们,因此我们只需要找到对应的 Ajax 请求,从中提取需要的信息就行
案例我们选用 豆瓣电影剧情片排行榜
(https://movie.douban.com/typerank?type_name=%E5%89%A7%E6%83%85&type=11&interval_id=100:90&action=)
1.找到 Ajax 请求
进入页面-->开发者工具-->Network-->XHR,然后下拉刷新
得到的就是每次刷新对应的 Ajax 请求了
2.分析 Ajax 请求的 Request URL
点击一个请求,查看 Headers 的 Request URL,就是该 Ajax 请求的 url
通过对比多条 url ,判断出 url 里每个参数的意思(url 问号后面的是参数),方便我们爬取多次刷新的数据
https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action=&start=20&limit=20
通过对比分析,推测如下:
type: 影片类型对应的编号,应为选择的是剧情片,所以都是11
interval_id: 是区间,就是页面右上方的好于多少多少的剧情片,100%3A90 应该就代表100%~90%,本次我们就只爬取这10%的580个影片信息
action:空的就先不用管了
start:应该是该 Ajax 请求的电影排名的起始位置
limit: 每次刷新的电影数量
所以根据需要,我们要变动的就只是 start 参数,就可以构造出对应的url了
# 构造url格式,{}是需要填的占位符,是影片的起始位置 url = 'https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action=&start={0}&limit=20' # 只爬取前580个电影信息,i用于填写其实位置 for i in range(0, 580, 20): # 生成每条Ajax的url ajax_url = url.format(str(i)) # 用get()请求 rsp = requests.get(ajax_url)
3.分析 Ajax 请求的 Preview
每条 Ajax 返回的数据都在它的 Preview 里面,这里返回的就是对应的电影信息,一般是 json 格式我们从这里面提取需要的信息就可以
根据返回的信息取出需要的每个数据
# 得到返回数据,movies是个list,每个元素是dict movies = rsp.json() # 遍历每个电影 for movie in movies: name = movie['title'] release_date = movie['release_date'] regions = movie['regions'] regions = ''.join(regions) types = movie['types'] types = ','.join(types) actors = movie['actors'] actors = ','.join(actors) score = movie['score'] # 写入本地文件 with open('douban.text', 'a', encoding='utf-8') as f: f.write('名字:'+name+'\n日期'+release_date+'\n地区'+regions+'\n类型'+types+'\n演员'+actors+'\n评分'+score+'\n\n')
结果展示:
全部代码:
import requests
# 构造url格式,{}是需要填的占位符,是影片的起始位置
url = 'https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action=&start={0}&limit=20'
# 只爬取前580个电影信息,i用于填写其实位置
for i in range(0, 580, 20):
# 生成每条Ajax的url
ajax_url = url.format(str(i))
# 用get()请求
rsp = requests.get(ajax_url)
# 得到返回数据,movies是个list,每个元素是dict
movies = rsp.json()
# 遍历每个电影
for movie in movies:
name = movie['title']
release_date = movie['release_date']
regions = movie['regions']
regions = ''.join(regions)
types = movie['types']
types = ','.join(types)
actors = movie['actors']
actors = ','.join(actors)
score = movie['score']
# 写入本地文件
with open('douban.text', 'a', encoding='utf-8') as f:
f.write('名字:'+name+'\n日期'+release_date+'\n地区'+regions+'\n类型'+types+'\n演员'+actors+'\n评分'+score+'\n\n')
github:https://github.com/JeesonZhang/pythonspider/blob/master/ajax