整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Python爬虫教程:采集快手用户所有公开作品,包括图集和视频!

在前面

  • 代码功能如题:根据快手用户的id来爬取用户所有公开作品,包括图集和视频。
  • 原理:其实就是利用基于chromium内核的浏览器自带的devtools对所有请求进行排查找出包含作品链接的请求,然后用代码模拟请求去获得数据,再根据url下载作品保存就行了,包括一些网站的自动注册登录、操作都可以模拟。这个其实应该算是写过爬虫的同学们都知道。

核心代码

  • 废话不多说,上核心代码
def __crawl_user(self, uid):
if uid.isdigit():
    uid = self.__switch_id(uid)

payload = {"operationName": "privateFeedsQuery",
           "variables": {"principalId": uid, "pcursor": "", "count": 999},
           "query": "query privateFeedsQuery($principalId: String, $pcursor: String, $count: Int) {\n  privateFeeds(principalId: $principalId, pcursor: $pcursor, count: $count) {\n    pcursor\n    list {\n      id\n      thumbnailUrl\n      poster\n      workType\n      type\n      useVideoPlayer\n      imgUrls\n      imgSizes\n      magicFace\n      musicName\n      caption\n      location\n      liked\n      onlyFollowerCanComment\n      relativeHeight\n      timestamp\n      width\n      height\n      counts {\n        displayView\n        displayLike\n        displayComment\n        __typename\n      }\n      user {\n        id\n        eid\n        name\n        avatar\n        __typename\n      }\n      expTag\n      __typename\n    }\n    __typename\n  }\n}\n"}
res = requests.post(self.__data_url, headers=self.__headers, json=payload)

works = json.loads(res.content.decode(encoding='utf-8', errors='strict'))['data']['privateFeeds']['list']

if not os.path.exists("../data"):
    os.makedirs("../data")

# 这两行代码将response写入json供分析
# with open("data/" + uid + ".json", "w") as fp:
#     fp.write(json.dumps(works, indent=2))

# 防止该用户在直播,第一个作品默认为直播,导致获取信息为NoneType
if works[0]['id'] is None:
    works.pop(0)
name = re.sub(r'[\\/:*?"<>|\r\n]+', "", works[0]['user']['name'])

dir = "data/" + name + "(" + uid + ")/"
# print(len(works))
if not os.path.exists(dir):
    os.makedirs(dir)

# if not os.path.exists(dir + ".list"):
#     print("")

print("开始爬取用户 " + name + ",保存在目录 " + dir)
print(" 共有" + str(len(works)) + "个作品")

for j in range(len(works)):
    self.__crawl_work(uid, dir, works[j], j + 1)
    time.sleep(1)

print("用户 " + name + "爬取完成!")
print()
time.sleep(1)

快手分为五种类型的作品,在作品里面表现为workType属性

  • 其中两种图集: vertical和multiple,意味着拼接长图和多图,所有图片的链接在imgUrls里
  • 一种单张图片: single 图片链接也在imgUrls里
  • K歌: ksong 图片链接一样,不考虑爬取音频...
  • 视频: video 需要解析html获得视频链接



def __crawl_work(self, uid, dir, work, wdx):
    w_type = work['workType']
    w_caption = re.sub(r"\s+", " ", work['caption'])
    w_name = re.sub(r'[\/:*?"<>|\r\n]+', "", w_caption)[0:24]
    w_time = time.strftime('%Y-%m-%d', time.localtime(work['timestamp'] / 1000))

if w_type == 'vertical' or w_type == 'multiple' or w_type == "single" or w_type == 'ksong':
    w_urls = work['imgUrls']
    l = len(w_urls)
    print("  " + str(wdx) + ")图集作品:" + w_caption + "," + "共有" + str(l) + "张图片")
    for i in range(l):
        p_name = w_time + "_" + w_name + "_" + str(i + 1) + ".jpg"
        pic = dir + p_name
        if not os.path.exists(pic):
            r = requests.get(w_urls[i])
            r.raise_for_status()
            with open(pic, "wb") as f:
                f.write(r.content)
            print("    " + str(i + 1) + "/" + str(l) + " 图片 " + p_name + " 下载成功 √")
        else:
            print("    " + str(i + 1) + "/" + str(l) + " 图片 " + p_name + " 已存在 √")
elif w_type == 'video':
    w_url = self.__work_url + work['id']
    res = requests.get(w_url, headers=self.__headers_mobile,
                       params={"fid": 1841409882, "cc": "share_copylink", "shareId": "143108986354"})
    html = res.text
    waitreplace = work['id'] + '".*?"srcNoMark":"(.*?)"'

    v_url = re.findall(waitreplace, html)
    # pattern = re.compile(r"playUrl", re.MULTILINE | re.DOTALL)
    # script = soup.find("script", text=pattern)
    # s = pattern.search(script.text).string
    # v_url = s.split('playUrl":"')[1].split('.mp4')[0].encode('utf-8').decode('unicode-escape') + '.mp4'
    try:
        print("  " + str(wdx) + ")视频作品:" + w_caption)
    except:
        print("  这里似乎有点小错误,已跳过")
    v_name = w_time + "_" + w_name + ".mp4"
    video = dir + v_name

    if v_url:
        if not os.path.exists(video):
            r = requests.get(v_url[0])
            r.raise_for_status()

            with open(video, "wb") as f:
                f.write(r.content)
            print("    视频 " + v_name + " 下载成功 √")
        else:
            print("    视频 " + v_name + " 已存在 √")
    else:
        print("未找到视频")
else:
    print("错误的类型")
  • payload就是post参数,这个是在devtools的request请求底下可以找到的
  • 其实就是解析json,然后里面有图片的url和视频的id,我注释掉的两行代码可以保存完整的json的,你可以去掉注释然后看分析保存的json
  • 剩下的看源码吧,不难理解的


  • 注意事项:

    • 不考虑提供列表可选的批量下载功能
    • 有需要的合理功能可以issue反馈,看到后会考虑是否修改
    • 如果需要自定义自己的需求,可以拿走代码自行修改,喜欢的话给个star给个follow
    • 本代码仅供学习使用,不可违反法律爬取视频,以及私自盗用搬运视频,后果自负

    项目源码地址 https://github.com/oGsLP/kuaishou-crawler

    网页中常见的多媒体文件包括音频文件和视频文件,对于在线音频和视频,我们往往都是使用embed标签来插入。embed语法:

    1 <embed src="”视频地址”" type="”audio/x-pn-realaudio-plugin”"

    2 console="”Clip1〃" controls="”ControlPanel,StatusBar”" height="”330〃"

    3 width="”450〃" autostart="”true”" title="undefined">

    <embed src="要播放的文件网址" ;="" autostart="true" loop="true" width="400"

    height="350">

    html中网页中如何插入音频和视频?


    举例1:插入音频文件

    1 <title>插入音频文件</title>

    2

    3

    4 <embed src="media/西班牙舞曲.mp3" width="400px" height="80px">

    在浏览器预览效果如下:

    说明:

    我们可以看到,使用embed标签插入音频文件还会有一个播放界面,界面上有几个简单的功能按钮。

    举例2:插入视频文件

    1 <title>插入音频文件</title>

    2

    3

    4 <embed src="media/小苹果.wmv" width="400px" height="80px">

    在浏览器预览效果如下:

    注意:

    由于音频和视频文件比较大,所以在这里我们就不提供大家在线测试的功能。不过大家可以在自己计算机上面测试一下代码。

    使用embed标签插入视频,在浏览器我们也可以看到,浏览器提供了一个简单的操作界面。embed标签支持的视频格式很多,大部分主流格式都支持。

    embed标签能支持大部分格式的视频文件,反正主流的如.mp4、.avi、.rmvb等都支持。如果你使用embed标签不能播放视频,那就可能是你视频格式有问题或者编码有问题。你可以用格式工厂转换一下格式。

    以上就是html中网页中如何插入音频和视频?

    . WebRTC 采集api

    在WebRTC中有一个api 可以用来获取桌面:getDisplayMedia

    var promise = navigator.mediaDevices.getDisplayMedia(constraints);

    constraints可选 constraints中约束与getUserMedia函数中的一致。

    2. 采集平面数据

    采集平面数据:这个功能在chrome中是实验性的项目,所以只有对最新的项目开放。

    在实战之前我们要打开浏览器,做一下设置 chrome://flags/#enable-experimental-web-platform-features

    如下图所示:

    接下来我们看看具体的js代码如下:

    C++音视频开发学习资料点击领取→音视频开发(资料文档+视频教程+面试题)(FFmpeg+WebRTC+RTMP+RTSP+HLS+RTP)