动态网页内容提取,照着阿星老师的教程动手实现的。用爬虫抓取动态加载数据丨Python爬虫实战系列(6)_互联网阿星的博客-CSDN博客_爬虫动态加载
思路分析
目标:获取分类电影的信息(名称+评分)
路线:进入豆瓣电影榜单的页面——点击分类类目——动态获取榜单内容——写入文件
进入具体类目
打开豆瓣电影排行榜的页面,分析元素可以得到,电影分类的获取是通过静态超链接的方式获取的,这里可以通过正则表达式来拼接不同分类的超链接来提取想要的数据,并定义选择菜单“menu”。
代码实现
# 获取所有电影的类型和对应type值
def get_all_type_films(self):
# 获取类型与类型码
url = 'https://movie.douban.com/chart'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'}
html = requests.get(url=url,headers=headers).text
re_bds = r'<a href=.*?type_name=(.*?)&type=(.*?)&.*?</a>'
pattern = re.compile(re_bds,re.S)
r_list = pattern.findall(html)
# 存放所有类型和对应类型码
type_dict = {}
# 定义电影类型的菜单
menu = ''
for r in r_list:
type_dict[r[0].strip()] = r[1].strip()
# 获取input的菜单,显示所有电影类型
menu += r[0].strip() + '|'
return type_dict,menu
具体类目榜单获取
经过观察,豆瓣的电影排行榜都是动态获取数据的,鼠标滚轮往下滚几下就会多出一个文件。因此这一步要不断发请求给服务器获取数据。
打开文件查看header分析可知,请求的url是由baseurl和type、il_id、action、start、limit的值构成,如下图。
分析参数可知:
type: 24 # 电影类型
interval_id: 100:90 #代表网页上滑动条的百分比(好于100%-90%的历史片)
action: '' # 空
start: 0 # 每次加载电影的起始索引值 0 20 40 60
limit: 20 # 每次加载的电影数量,1为初始值,后续加载时20固定不变
再刷新页面,每次刷新都有三个固定的数据包,点开发现其中一个是总共有多少部电影,其他两个是列表前20项和列表范围的信息。
获取电影总数
def total_number(self, type_number):
# type表示电影类型
url = 'https://movie.douban.com/j/chart/top_list_count?type=24&interval_id=100%3A90'.format(type_number)
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'}
html = requests.get(url=url,headers=headers).json()
total = int(html['total'])
return total
获取某一类电影全部信息(并写入文件)
import requests
import time
import random
import re
import json
class DoubanSpider(object):
def __init__(self):
self.url = 'https://movie.douban.com/j/chart/top_list?'
self.i = 0
# 获取页面
def get_page(self, params):
# 将json转换为 python 数据类型,并返回
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'}
html = requests.get(url=self.url, params=params, headers=headers).text
html = json.loads(html)
self.parse_page(html)
# 解析并保存数据
def parse_page(self, html):
item = {}
with open('movie_type.txt', 'a', encoding='utf-8') as f:
for one in html:
# 名称 + 评分
item['name'] = one['title'].strip()
item['score'] = float(one['score'].strip())
print(item)
f.write(str(item) + '\n')
self.i += 1
# 获取电影总数
def total_number(self, type_number):
# type表示电影类型
url = 'https://movie.douban.com/j/chart/top_list_count?type=24&interval_id=100%3A90'.format(type_number)
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'}
html = requests.get(url=url,headers=headers).json()
total = int(html['total'])
return total
# 获取所有电影的类型和对应type值
def get_all_type_films(self):
# 获取类型与类型码
url = 'https://movie.douban.com/chart'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'}
html = requests.get(url=url,headers=headers).text
re_bds = r'<a href=.*?type_name=(.*?)&type=(.*?)&.*?</a>'
pattern = re.compile(re_bds,re.S)
r_list = pattern.findall(html)
# 存放所有类型和对应类型码
type_dict = {}
# 定义电影类型的菜单
menu = ''
for r in r_list:
type_dict[r[0].strip()] = r[1].strip()
# 获取input的菜单,显示所有电影类型
menu += r[0].strip() + '|'
return type_dict,menu
# 主程序入口函数
def main(self):
# 获取type的值
type_dict,menu = self.get_all_type_films()
menu = menu + '\n从上方选择本次爬取分类:'
name = input(menu)
type_number = type_dict[name]
# 获取电影总数
total = self.total_number(type_number)
# 构建文件
with open('movie_type.txt', 'w', encoding='utf-8') as f:
f.write("分类电影数据:\n")
for start in range(0,(total+1),20):
#构建查询参数
params = {
'type': type_number,
'interval_id': '100:90',
'action': '',
'start': str(start),
'limit': '20'
}
# 调用函数,传递params参数
self.get_page(params)
# 随机休眠1-3秒
time.sleep(random.randint(1,3))
print('电影总数量:%d部'%self.i )
if __name__ == '__main__':
spider = DoubanSpider()
spider.main()