Ajax介绍及爬取哔哩哔哩番剧索引追番人数排行
Ajax,是利用JavaScript在保证页面不被刷新,页面链接不改变的情况下与服务器交换数据并更新部分网页的技术。简单的说,Ajax使得网页无需刷新即可更新其内容。举个例子,我们用浏览器打开新浪微博,进入某个用户的页面,当我们浏览到该页末尾时,会出现一个加载的动画,然后就刷新出来的新的微博内容,这个过程并不需要我们手动的刷新网页。
Ajax的原理:发送Ajax请求到网页更新的这个过程可分为三步:
1.发送请求
2.解析内容
3.渲染网页
详细的原理介绍可参照:https://www.cnblogs.com/wanghp/p/6991554.html
简单的说,JavaScript新建了一个XMLHttpRequest对象,然后调用onreadystatechange属性设置了监听,然后调用open()方法和send()方法向服务器发送了请求,当服务器返回响应时,监听对应的方法便会触发,然后在方法里解析响应的内容,从而实现了无需刷新便能更新网页。
那么如何查看Ajax请求呢?以爬取哔哩哔哩番剧索引追番人数排行为例,我们使用Chrome浏览器打开https://www.bilibili.com/anime/index/#season_version=-1&area=-1&is_finish=-1©right=-1&season_status=-1&season_month=-1&pub_date=-1&style_id=-1&order=3&st=1&sort=0&page=1,并按F12打开开发者工具,如图所示:
在开发者工具中切换到Network选项卡,然后重新刷新页面,筛选XHR请求类型,如图所示:
在左边找到我们需要爬取的Ajax请求,即
点击header可以查看该请求的header信息,之后我们会用到。
Preview是该请求返回的响应内容,包含了我们所要爬取的信息。
接下来我们以爬取b站追番人数排行榜为例来介绍如何提取Ajax结果:
首先在header中找到请求链接,即Request URL:
接着找到该请求的参数信息:
观察到每次翻页,page参数+1,其他参数没有改变,所以我们每次请求时只需要改变page参数即可。
下面给出代码示例:
1 from urllib.parse import urlencode 2 import requests 3 import time 4 import csv 5 import os 6 7 base_url = "https://bangumi.bilibili.com/media/web_api/search/result?" 8 9 headers = { 10 \'Host\':\'bangumi.bilibili.com\', 11 \'Referer\':\'https://www.bilibili.com/anime/index/\', 12 \'User_Agent\':\'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36\', 13 \'Origin\': \'https://www.bilibili.com\', 14 } 15 16 def get_page(page): 17 #参数 18 params = { 19 \'season_version\':\'-1\', 20 \'area\': \'-1\', 21 \'is_finish\': \'-1\', 22 \'copyright\': \'-1\', 23 \'season_status\': \'-1\', 24 \'season_month\':\'-1\', 25 \'pub_date\': \'-1\', 26 \'style_id\': \'-1\', 27 \'order\': \'3\', 28 \'st\': \'1\', 29 \'sort\': \'0\', 30 \'page\': page, 31 \'season_type\':\'1\', 32 \'pagesize\':\'20\' 33 } 34 url = base_url + urlencode(params) 35 try: 36 response = requests.get(url,headers=headers,allow_redirects=False) 37 #将内容解析为json格式返回 38 return response.json() 39 except requests.ConnectionError as e: 40 print(\'Error\',e.args) 41 42 def parse_page(json): 43 if json: 44 items = json.get(\'result\').get(\'data\') 45 for item in items: 46 ret = {} 47 ret[\'title\'] = item.get(\'order\').get(\'title\') 48 ret[\'score\'] = item.get(\'order\').get(\'score\') 49 ret[\'play\'] = item.get(\'order\').get(\'play\') 50 ret[\'follow\'] = item.get(\'order\').get(\'follow\') 51 ret[\'index_show\'] = item.get(\'index_show\') 52 ret[\'is_finish\'] = item.get(\'is_finish\') 53 yield item 54 55 #写入文件 56 def write_to_file(items): 57 with open("bilibili.csv","a+") as csvfile: 58 writer = csv.writer(csvfile) 59 for item in items: 60 print(item) 61 writer.writerow([item[\'order\'][\'follow\'],item[\'title\'],item[\'order\'][\'score\'], 62 item[\'order\'][\'play\'],item[\'index_show\'],item[\'is_finish\']]) 63 64 65 def main(offset): 66 json = get_page(offset) 67 results = parse_page(json) 68 write_to_file(results) 69 return 0 70 71 72 if __name__ == \'__main__\': 73 for page in range(1,11): 74 main(offset=page) 75 time.sleep(1) 76 77
运行结果: