首页 > 编程语言 >Python爬取快手博主所有视频

Python爬取快手博主所有视频

时间:2022-12-28 17:31:34浏览次数:43  
标签:__ upper Python 手博主 取快 ks video user data

随着互联网经济的快速发展和自媒体行业的普及,越来越多的视频创作者加入了短视频平台,不仅快速的推动了短视频平台行业的发展,也给大众带来了更多新鲜有趣的知识和内容。


据最新数据显示,短视频用户规模为8.88亿,较2020年12月增长1440万,占网民整体的87.8%。数据显示,2021年3月,短视频APP的人均单日使用时长为125分钟,较长视频高出27分钟,且差距呈增长趋势;53.5%的短视频用户每天都会看短视频节目,这一比例较长视频(36.3%)高出17.2个百分点。


可见短视频占据了我们不少的日常生活时间,那么如何从短视频平台快速筛选到有效的信息呢,由此引入我们今天的内容,爬取快手指定博主的作品,这样可以避免我们观看短视频的时候,分散我们的注意力,也可以更高效的获取到我们想要的内容。


话不多说,直奔主题,首先打开快手网页版,选取一个指定博主的主页进行打开。主页链接如下:

https://www.kuaishou.com/profile/3xxcvi49q2r52gu


请记得选择用户登陆,出于两个方面考虑:

  1. 只有登陆后才能看到博主的全部视频
  2. 后面的视频列表获取需要使用到cookie

在浏览器打开页面后,通过 F12 调出审查元素界面,然后切到NetWork重新刷新界面。得到数据如下图:


Python爬取快手博主所有视频_json


嗯?一看这个数据,还真是瞌睡遇到枕头,这up主的数据相关信息已到手,那么切到请求信息看看需要哪些数据?


Python爬取快手博主所有视频_ide_02

Python爬取快手博主所有视频_数据_03


Python爬取快手博主所有视频_ide_04


通过以上几张截图,可以看到获取up主相关信息请求所需的数据,请求地址,请求头,请求方法,请求数据格式,用户cookie以及user_id, 用户ID的获取方法也很简单明了,如图所示即用户主页最后的一串字符串即可获取。


接着往下点击,看看能否找到视频数据信息,没看到有其他的链接,接着点击graphql,嗯,这…


Python爬取快手博主所有视频_数据_05


可以通过这个接口清楚的看到,返回的feed里面的数据好像是当前页面的视频信息,额,不好意思,用词不当,不是好像而是就是。此时的我彷佛有点飘了,来看看请求视频列表信息需要哪些数据。


Python爬取快手博主所有视频_数据_06


关于获取视频列表请求头的信息不做过多赘述,参考获取up主相关信息的请求头。主要来说一下数据,query里面的内容是固定,我们需要关注的是红框框住的内容,可以清楚的看到userId,pcursor,page三个参数,userId刚说过了,page是个固定的字符串,关键点在于pcursor,这玩意是干嘛用的,目前还不知道。


刚才请求的只是一页的数据,当作品多的时候数据结构是什么样的呢?接着滚动下页面,发现同样发送了一个请求,请求数据如下图:


Python爬取快手博主所有视频_ide_07


可以看到pcursor竟然有了值,那么值从哪里来的呢,通过接口返回的数据比对发现,他的值是由上一次视频列表中返回的pcursor,如下图:


Python爬取快手博主所有视频_数据_08


那么什么时候视频数据全部加载完呢,我们一直往下拉,拉到最后没数据的时候发现pcursor的值为no_more时,则用户的视频数据已经加载完毕了,如下图 :


Python爬取快手博主所有视频_ide_09


上面的逻辑已经分析完毕了,接下来进入编码环节,代码如下:


#!/usr/bin/env python
# -*- coding:utf-8 -*-
import os
import time
import requests
import json




class KsStd(object):
ksHeaders = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)'
' Chrome/98.0.4758.82 Safari/537.36',
'content-type': 'application/json',
'Host': 'www.kuaishou.com',
'Origin': 'https://www.kuaishou.com',
'Cookie': "did=web_dd78404c06b81b5ec9934816c5068807; didv=1652079520588; _bl_uid=Opl4j2jvybvdskkb"
"gt0v8gv6dggz; kpf=PC_WEB; kpn=KUAISHOU_VISION; clientid=3; userId=1843103571; kuaishou."
"server.web_st=ChZrdWFpc2hvdS5zZXJ2ZXIud2ViLnN0EqABflkKr9RDu5xiek9c8QGs2xMA1WPfpNmrhj1yN"
"LYL1DTa9CSGXREEsvGjkZmbsTevXb9KfjuM0Loc5FfRGSpkptr07YoE0xIL9qD6wjaPbNGYSzYW2tVYGpXCiUP"
"eas8MBS_Rpf9CiTiSAGlM_ZVPlm4I-n0HLcBr8ahBkQK0CfShogzrOdqtNrmSeTYofISUwu7NfKgJiFCb7"
"Y-gHXklFhoSBmjJ_SI5Snf4O3WXJiYJKm0lIiCamuTlwoSafyegLDSa3y5gJhH50rhBp_Eonl0FPPIv2ygFMAE; "
"kuaishou.server.web_ph=5b0603df2789bb23dcd6959cda23f59ed81e"
}
ks_base_url = "https://www.kuaishou.com/graphql"


def __init__(self):
pass


# 构建公共接口请求头部
def header_data_build(self, meg_param={}):
meg_param.update(self.ksHeaders)
return meg_param


# 请求用户主页
def req_monitor(self, profile_url):
ks_user_id = profile_url.split('/')[-1]
ks_headers = self.header_data_build({'Referer': profile_url})
# upper 信息
self.ks_upper_api_data(ks_user_id, ks_headers)
# 视频信息
self.handle_video_info(ks_user_id, ks_headers)
print("程序待机中……")


# 构建快手 upper apiData
def ks_upper_api_data(self, ks_user_id, ks_headers):
ks_upper_data = {
"operationName": "visionProfile",
"variables": {
"userId": ks_user_id
},
"query": "query visionProfile($userId: String) {\n visionProfile(userId: $userId) {\n"
" result\n hostName\n userProfile {\n ownerCount {\n "
"fan\n photo\n follow\n photo_public\n __"
"typename\n }\n profile {\n gender\n user_name\n "
"user_id\n headurl\n user_text\n user_profile_bg_url\n "
"__typename\n }\n isFollowing\n __typename\n }\n __typename\n }\n}\n"
}
upper_data = requests.post(url=self.ks_base_url, headers=ks_headers, data=json.dumps(ks_upper_data)).json()
self.upper_info_detail(upper_data['data']['visionProfile']['userProfile'])


# 构建用户信息
def upper_info_detail(self, user_data):
upper_infos = {}
upper_infos['nickname'] = user_data['profile']['user_name']
upper_infos['signature'] = user_data['profile']['user_text']
upper_infos['uid'] = user_data['profile']['user_id']
upper_infos['video_count'] = user_data['ownerCount']['photo_public']
upper_infos['avatar'] = user_data['profile']['headurl']
upper_infos['attention'] = user_data['ownerCount']['follow']
upper_infos['fans'] = user_data['ownerCount']['fan']
upper_infos['create_time'] = int(time.time())
print("用户信息", upper_infos)


# 构建快手 video apiData
def ks_video_api_data(self, ks_user_id, ks_headers, pcursor_index=""):
ks_video_data = {
"operationName": "visionProfilePhotoList",
"variables": {
"userId": ks_user_id,
"pcursor": pcursor_index,
"page": "profile"
},
"query": "fragment photoContent on PhotoEntity {\n id\n duration\n "
"caption\n likeCount\n viewCount\n realLikeCount\n coverUrl\n "
"photoUrl\n photoH265Url\n manifest\n manifestH265\n videoResource\n "
"coverUrls {\n url\n __typename\n }\n timestamp\n expTag\n "
"animatedCoverUrl\n distance\n videoRatio\n liked\n stereoType\n "
"profileUserTopPhoto\n __typename\n}\n\nfragment feedContent on Feed {\n "
"type\n author {\n id\n name\n headerUrl\n following\n "
"headerUrls {\n url\n __typename\n }\n __typename\n }\n "
"photo {\n ...photoContent\n __typename\n }\n canAddComment\n "
"llsid\n status\n currentPcursor\n __typename\n}\n\nquery "
"visionProfilePhotoList($pcursor: String, $userId: String, $page: String, "
"$webPageArea: String) {\n visionProfilePhotoList(pcursor: $pcursor, userId: "
"$userId, page: $page, webPageArea: $webPageArea) {\n result\n llsid\n "
"webPageArea\n feeds {\n ...feedContent\n __typename\n }\n "
"hostName\n pcursor\n __typename\n }\n}\n"
}
video_data = requests.post(url=self.ks_base_url, headers=ks_headers, data=json.dumps(ks_video_data)).json()
return video_data['data']['visionProfilePhotoList']


# 构建 视频信息
def handle_video_save(self, video_datas):
for videoItem in video_datas:
video_whv = videoItem['photo']['manifest']['adaptationSet'][0]['representation'][0]
video_title_data = videoItem['photo']['caption'].split()
video_save_data = {
'title': video_title_data[0],
'desc': videoItem['photo']['caption'],
'share_url': videoItem['photo']['photoUrl'],
'digg_count': videoItem['photo']['likeCount'],
'play_count': videoItem['photo']['viewCount'],
'uid': videoItem['author']['id'],
'music_url': videoItem['photo']['photoH265Url'],
'video_url': videoItem['photo']['photoUrl'],
'duration': videoItem['photo']['duration'],
'width': video_whv['width'],
'ratio': video_whv['qualityType'],
'height': video_whv['height'],
'origin_cover': videoItem['photo']['coverUrl'],
'create_time': videoItem['photo']['timestamp'] / 1000,
}
tags = ""
for index, tag in enumerate(video_title_data[1:]):
if index == len(video_title_data[1:]) - 1:
tags += tag.replace("#", "")
else:
tags += tag.replace("#", "") + ";"
video_save_data.update({'tags': tags})
try:
video_save_data.update({'aweme_id': videoItem['photo']['videoResource']['hevc']['videoId']})
except Exception as e:
video_save_data.update({'aweme_id': "hexId888nonevideoId112"})
print(video_save_data)
# 保存视频方法自行扩展


# 构建 视频请求 信息 && 合并为一起
def handle_video_info(self, ks_user_id, ks_headers):
the_video_datas = []
page_index = ""
while page_index != 'no_more':
video_data = self.ks_video_api_data(ks_user_id, ks_headers, page_index)
page_index = video_data['pcursor']
the_video_datas += video_data['feeds']
time.sleep(20)
print(the_video_datas)
self.handle_video_save(the_video_datas)




if __name__ == "__main__":
profile_url = "https://www.kuaishou.com/profile/3xs8937rkv7u256"
ks = KsStd()
ks.req_monitor(profile_url)




标签:__,upper,Python,手博主,取快,ks,video,user,data
From: https://blog.51cto.com/u_15924937/5975847

相关文章

  • sublime安装REPL无法执行python3.7版本
    一、下载sublime最新版本地址:SublimeText-TextEditing,DoneRight单击DOWNLOADFORWINDOWS需要等一会儿自己就下载了。  安装就是下一步就可以了。二、安装......
  • python 使用thread多线程执行耗时代码
    python使用thread多线程执行耗时代码1、引入所需要的包importqueueimportthreadingimporttraceback2、定义线程类:classThreadService(threading.Thread):  de......
  • Python对象的比较和拷贝
    Python对象的比较和拷贝本文内容存在主观理解,详细请查阅官网文档比较(==VSis)==操作符是比较对象的值是否相等,而is比较的事对象的身份标识是否相等,即它们是否是同一......
  • tensorflow_probability.python.bijectors的一些使用
      网上见到一个TensorFlow的代码,没见过这个形式的,是概率编程的代码:#coding=utf-8#Copyright2020TheTF-AgentsAuthors.##LicensedundertheApacheLicens......
  • python中global 和 nonlocal 的作用域
    python引用变量的顺序: 当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量。一globalglobal关键字用来在函数或其他局部作用域中使用全局变量。......
  • 【leetcode】3: 无重复字串的最长子串(python)
    给定一个字符串s,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1:输入:s="abcabcbb"输出:3解释:因为无重复字符的最长子串是"abc",所以其长度为3......
  • [oeasy]python0033_回车_carriage_return_figlet_字体变大
    回到开头回忆上次内容进程前后台切换<kbd>ctrl</kbd>+<kbd>z</kbd>把当前进程切换到后台并暂停​​jobs​​查看所有作业用​​fg​​可以把后台进程再切回前台​​......
  • python logging配置
    python中,logging由logger,handler,filter,formater四个部分组成。logger是提供我们记录日志的方法;handler是让我们选择日志的输出地方,如:控制台,文件,邮件发送等,一个logger添加......
  • python中的mysql操作教程及实例
    一.数据库在自动化测试中的应用存测试数据有的时候大批量的数据,我们需要存到数据库中,在测试的时候才能用到,测试的时候就从数据库中读取出来。这点是非常重要的!存测试结......
  • 数值计算:前向和反向自动微分(Python实现)
    1自动微分我们在《数值分析》课程中已经学过许多经典的数值微分方法。许多经典的数值微分算法非常快,因为它们只需要计算差商。然而,他们的主要缺点在于他们是数值的,这意味......