Python爬虫系列之爬取付费网站课程思路


0x00 前记

国际惯例来张图:D

Python
在考试备战群中发现有人在卖付费网站的视频,还号称整个站的课程都可以拿到。刚好自己也需要,但是又不(mei)想(qian)购买。

0x01 如何拿到付费视频播放地址的分析思路

很明显就是抓包而已嘛,废话不多说,开个Chrome,点击试看的视频F12 走起,三下五除二,直接就看到了原视频地址,右键打开就能在线看。这不是 So easy 吗?还拿来卖钱。。。

但是接下来我就碰到问题了,每个课程只有第一个视频是免费看的,其他的都是要登录购买才能看的,这就很尴尬了,没有加载视频的请求,F12 再厉害也拿不到原视频地址啊。

下面是我解决问题的思路,仅供参考:

  • 第一步,分别打开两到三个课程查看他免费的视频,用上面的步骤(即 F12 找到原视频地址),然后列出来进行分析。
    1
    2
    3
    https://xxx.com/xxx?vid=aaa&siteid=bbb......
    https://xxx.com/xxx?vid=qqq&siteid=bbb......
    https://xxx.com/xxx?vid=sss&siteid=bbb......

我发现每个视频唯一的区别就是 vid 了,后面的一长串都是一致的,如果懒得肉眼看可以直接扔 Beyond Compare 这个神器对比或者任何在线文本对比工具,这里只是提一嘴,我还是用肉眼看出来的。。

  • 第二步,知道了vid是关键了(猜测vidvideoid的缩写),分析他的规律。
    1
    2
    6ED700F4A2324C1C9C44DC5901407461
    11F0249EA74CBDB19C44DC5901407461

类似于这种,感觉是32位的哈希值,找出规律可能性不大。
所以我又卡住了,又想起了那个卖课程的说他端了整个站。难道前端搞不定,他是拿下了站然后拖了库。
于是我又Google了一下,发现这个网站15年确实报了一个漏洞,但是好像没修复。
渗透?这就是很尴尬了,触及到我的知识盲区了。。。
知识盲区

发给一位大佬,他看了一下说里面的数据库是空的,所以应该不是,也不太可能是删库的情况,假定他拿到的权限很高可以删库,但是网站无法运行对他没有好处,况且现在网站还是运行状态,难道我被骗了?看了一下那个卖课程的微信,很一般啊,基本找不到和IT相关的,这真的是一个深藏不露的白帽子吗?

  • 第三步,我还是决定从前端入手,直接查看源代码发现课程列表的每个视频(不管是付费还是非付费)都有一个data-id,我感觉我一直忽略了网站本身的请求。又看了一下网站本身的请求,果不其然,试看的视频 有一个通过data-id去获取vid的请求。而付费的视频需要登录,好吧,我就点击登录(用的QQ小号),点击获取,果然看到了一样的请求,拿到了vid,哇哈哈哈,我本来都放弃希望了。原来竟然要登录。。
  • 第四步,一个个点击复制也太麻烦,果断用Python,复(yu)习一下也好:)

0x02 代码的大纲

拿到目标网页的源代码,解析得到想要的值

1
2
3
4
5
6
7
8
9
10
11
# -*- coding: UTF-8 -*-
import requests
import bs4
root_url = '网站地址'
index_url = root_url + '课程ID'
def get_video_data_id():
response = requests.get(index_url)
soup = bs4.BeautifulSoup(response.text, "lxml")
# BeautifulSoup中的select方法,这里的'=' 是完全匹配,即有只个Class名称的才能匹配到;'^=' 是模糊匹配,即有这个Class名称的就能匹配到
return[a.attrs.get('data-id') for a in soup.select('div.list-box a[class^=keshi_box]')]

模拟 POST 请求

在这里要提下的坑就是我一开始只用Cookies一直登陆不成功,最后被大佬们点醒,用curl命令(Windowsgit bash可用,Linux就更不用说了)去模拟登陆还是不行,然后直接用的Chrome下的Copy as cURL ,模拟成功,这步卡了最久,一直以为是requests的写法有问题,用requests的理由是感觉比urllib(x)简洁些,最最后将复制下的参数放到header

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import json
headers={'Accept-Encoding' : 'gzip, deflate',
'Accept-Language' : 'zh-CN,zh;q=0.8',
'Upgrade-Insecure-Requests' :'1',
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36',
'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Cache-Control' : 'max-age=0',
'Cookie' : '一串很长的直接复制哦',
'Proxy-Connection' : 'keep-alive'}
class JSONObject:
def __init__(self, d):
self.__dict__ = d
def get_videoid_by_post(id):
r = requests.post(post_url, headers=headers, data={'id':id})
# 解析Json对象
return json.loads(r.text,object_hook=JSONObject)

main方法定义及其调用

1
2
3
4
5
6
def main():
data_id = get_video_data_id();
for id in data_id:
a = get_videoid_by_post(id);
print(a.节点名称.想要的值);
main();

0x03 参考资料

快速上手— Requests 2.18.1 文档 - Python Requests
python3-cookbook 之读写 JSON 数据
使用 Python 轻松抓取网页

0x04 后记

感觉拿别人的收费视频不是很适合,纠结了一下不知道到底写不写这篇文章,虽然可能只有我一个人在看,所以在这里只分享一下思路,只做知识探讨。如有不妥,若有任何意见,可以留言(本站用的是disqus,将其放进pac即可看到或者全局):)

如果觉得我的文章对您有帮助,请随意打赏~

图片名称