业务场景
1.我的业务场景:
从Facebook平台,获取直播视频分析数据(用于数据统计)
2.适用的业务场景:
Facebook开发平台第三方应用开发
Puppeteer爬取Facebook/其他网页数据
技术方案
1. 应用接口获取: 在facebook开发平台注册facebook应用,使用接口获取数据
2. excel数据导入: 在facebook的视频分析主页中,导出视频分析数据,再使用PHPExcel导入数据库
3. 爬虫扒取网页:puppeteer登陆facebook后,模拟用户界面操作,读取dom元素,获取相关视频数据
说明
1. 以下facebook均简称为 fb
2. page_id 实际是视频主播在fb平台的唯一ID标识 (即主页和主播是一一对应的)
3. 因为三种方案分别涉及不同的技术工具,牵扯的代码片段和细节较多,为了不影响读者了解本次逻辑流程,我会另外写三篇博客来介绍各自的技术工具,以及相关细节和demo
4. 欢迎提出不同见解,有遗漏之处还望指出,谢谢
第一种方案: 应用接口获取
1.涉及工具:
1) facebooke开发应用平台
2. 逻辑流程(操作步骤):
1) 注册/设置开发者应用 =>
2) 下载fb-PHP-SDK =>
3) 手动获取所有主播的page_id =>
4) 接口获取page信息(根据page_id)+视频ID列表(过滤留下直播视频ID列表) =>
5) 接口获取video分析数据(根据video_id)
3. 涉及的接口
1) 获取page信息接口(page_id为必填参数)
A) 接口信息如图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190616191546572.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2R1cmluZ25vbmU=,size_16,color_FFFFFF,t_70)
B)代码片段:
/**
* 获取主页信息
* @param string $pageId 主页ID
* @param int $monthAgo 几个月前,默认2个月
* @param int $endTime 某个时间的时间戳
*/
public function getFBPageInfo($pageId , $monthAgo = 2, $endTime = null) {
$this->fb = new Facebook\Facebook([
'app_id' => '应用ID', // 应用ID
'app_secret' => '应用secret', //应用secret
'default_graph_version' => 'v3.2', // 应用版本号,我使用的是v3.2
]);
# 默认获取当天-前两个月的数据
$currDay = strtotime(date('Y-m-d 00:00:00'));
$untilTime = !empty($endTime) && $endTime < $currDay ? $endTime : $currDay; //指定时间戳|当天凌晨
$sinceTime = strtotime("-$monthAgo month", $untilTime); //2个月前的(指定日期|今天)凌晨
//$queryStr = '1349433135167312?fields=name,global_brand_page_name,fan_count,category,id,verification_status,videos.since(1555806977).until(1556460756).limit(100){length,id,title,content_category,created_time,updated_time,live_status}'; //20190421-20190428
$queryStr = $pageId .'?fields=name,global_brand_page_name,fan_count,category,id,verification_status,videos.since('.$sinceTime.').until('.$untilTime.').limit(100){length,id,title,content_category,created_time,updated_time,live_status}'; // 获取指定时间内的主页信息+video_id列表
$response = $this->fb->get($queryStr, self::$fbAccessToken);
$data = $response->getDecodedBody();
return $data;
}
2) 获取视频详情接口(video_id为必填参数)
A) 接口信息如图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190616192032650.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2R1cmluZ25vbmU=,size_16,color_FFFFFF,t_70)
B) 代码片段:
/**
* 获取单个视频分析数据
* @param string $videoId 视频ID
*/
public function getFBVideoAnalysisData($videoId) {
# 获取视频详情信息(视频简介+分析数据)
$this->fb = new Facebook\Facebook([
'app_id' => '应用ID', // 应用ID
'app_secret' => '应用secret', //应用secret
'default_graph_version' => 'v3.2', // 应用版本号,我使用的是v3.2
]);
$queryStr = $videoId . '/?fields=id,length,live_status,picture,created_time,updated_time,title,content_category,video_insights{id,name,title,values}';
$response = $this->fb->get($queryStr, self::$fbAccessToken);
$data = $response->getDecodedBody();
return $data;
}
3.遇到的问题&解决方案:
1) 问题一: 如果筛选出直播视频
答: 使用 获取主页信息中的video列表中的live_status字段值进行区分,live_status="VOD"的为直播视频
2) 问题二: 如何获取指定时间范围内容的视频列表
答:fb早期是支持FQL写法的,FQL类似SQL语法的一种fb查询语句,直接通过fb接口请求FQL字符串,就可以获取查询结果,但是fb现在已经不支持FQL语法格式; 但是根据技术直觉+不断调试,发现还有有迹可循的,比如上述获取主页信息接口的截图中使用的语句就是: //$queryStr = '1349433135167312?fields=name,global_brand_page_name,fan_count,category,id,verification_status,videos.since(1555806977).until(1556460756).limit(100); 其中page_id=1349433135167312,since表示查询起始时间,until表示查询截止时间,均为时间戳格式,limit(100),表示获取查询结果的前100条数据
3)问题三: 如何实时验证fb用户登录状态
答: 因为使用的是fb的Graph-SDK(图谱API),所以直接调用获取用户信息接口即可,若登录态未失效,则返回用户信息,否则抛出异常信息: "Invalid OAuth access token."(返回该SDK中,所有请求都需要先验证access_token,而access_token生产过程:是在用户授权登录,并且登录成功后,返回的一次性code和status作为请求参数,去请求fb接口生成的access_token),因此token失效等同于用户登录态失效
4)问题四: 如何获取提高开发应用的接口使用频率上限
答:应用接口调用频率为 (200*应用用户数量)/小时,例如我的应用有三个用户,则接口调用频率为600次/小时,这个600次是应用在一个小时之内的所有用户接口总调用次数,可以是用户A 调用599次,用户B调用1次,用户C 调用0 次,而非每个用户200次;
5)问题五:如何获取用户信息和直播视频信息,需要哪些权限授权
答:因为是内部使用,所以我没有经过审核,但是审核流程并不复杂,只需要使用接口将数据导入到数据库,并展示在应用网页中,即可提交审核,但务必保证是真实数据,不要使用自己造的假数据;详情见官方文档; 若是允许公开对外部可见的话,建议细分一下权限,一来公开需要审核权限,二来可以最大程度提高用户体验![在这里插入图片描述](https://img-blog.csdnimg.cn/20190616202215503.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2R1cmluZ25vbmU=,size_16,color_FFFFFF,t_70)
6) 问题六:用户登录开发应用的前提条件
答:
有两种情况:
A)情况一:
应用已通过fb审核,对所有fb用户可见,fb用户只需使用fb账号进行授权登录即可
B)情况二:
应用未通过权限审核,仅对部分用户可见; 首先必须在应用配置中添加访问用户,然后这些访问用户,使用fb账号进行登录应用即可
C)二者相同点:
无论是否通过审核,用户都必须使用fb第三方登录,进行fb用户授权(基于Auth2.0第三方授权机制)
D)注意:因为是内部使用,所以我没有经过审核,但是审核流程并不复杂,只需要使用接口将数据导入到数据库,并展示在应用网页中,即可提交审核,但务必保证是真实数据,不要使用自己造的假数据;详情见官方文档,
7)问题七:调试工具使用及注意事项
答:
调试工具链接: https://developers.facebook.com/tools/explorer/
A)注意事项: 调试工具必须要先进行授权,用到哪些权限就进行相关授权,为了方便,我是授权所有权限,有兴趣的同步可参照官方文档进行细分
B) 调试工具调用接口后,可以保存调用记录,可以得到一个会话ID: session_id,若有问题,可以去官方平台进行bug上报,并附上session_id
C) 使用如图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190616202226496.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2R1cmluZ25vbmU=,size_16,color_FFFFFF,t_70)
4.注意事项:
1) 因fb视频内容版权限制,接口获取到的视频ID不全,
2) 视频部分参数随时间增长而增长,需要定时更新,
3) fb应用/接口所有操作均依赖用户授权,即只有在用户登录时/接口token有效时,才能同步/更新fb数据到本地
4) 注意应用配置问题,***因为涉及的内容和细节较多,应用配置和sdk使用细节会单独写一篇博客描述,这篇博客主要以逻辑描述为主,具体操作请见后续博客
5.小结:
1) 优点: 客户端操作简单;
2) 缺点: 涉及版本的视频数据无法获取,导致数据不全 [这涉及到fb的隐私版权限制,经和fb工作人员沟通无果,但数据不全其实是比较致命的,但是本次应用开发经验对其他应用功能开发依然有借鉴意义]
第二种方案: excel数据导入
1.涉及工具:
Facebook数据分析主页
PHPExcel
2. 逻辑流程(操作步骤):
1)导出指定时间内的video_excel =>
2)用户在前端上传excel文件 =>
3)后端接收后,使用PHPExcel读取excel文件(/tmp/临时文件名) =>
4)将相关文件内容存入数据库
3.遇到的问题&解决方案:
1) 问题一: PHPExcel的基本使用
答: 因为涉及到代码模块,篇幅可能比较大,为了不干扰读者,本文以开发逻辑描述为主,PHPExcel的简单使用会单独写一遍博客描述
2) 问题二: 文件在哪里导出? 导出文件有哪些格式要求?
答:
A) 在视频分析数据主页右上角有个导出按钮;
B) 文件可以导出xls格式(excel文件),也可以导出csv格式
C) 注意事项: 务必使用xls格式导出,因为经过二者对比视频数据,发现xls文件中数据比csv文件中要齐全的多,虽然csv读取操作会更简单(PHP中使用file_get_content可以直接读取csv文件,返回一个多维数组;而读取xls文件需要借助于第三方类库,本次使用PHPExcel)
D) 操作步骤使用说明如图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190616204812870.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2R1cmluZ25vbmU=,size_16,color_FFFFFF,t_70)
4.注意事项:
1) excel导出时间,点击选择的时间点是当天凌晨00:00:00,即20190501表示20105-01 00:00:00;若想导出201905整月数据:20190501-20190601,而不是20190501-20190531
2) 友情提示: PHPExcel 官方更新截止到2019年1月,因时间精力有限,本次依旧使用PHPExcel, 新版本官方类库github链接: https://github.com/PHPOffice/PhpSpreadsheet
3) fb导出的excel文件内容可能为xml/html/xls格式,可统一另存为xlsx格式,再使用PHPExcel处理(务必打开再另存为xlsx,直接修改文件后缀名无效; 方法亲测有效)
5.小结:
1)优点: 数据比第一种方案完善,可获取所有视频数据;
2)缺点:需要客户端配合导入excel数据);PHP读取excel文件内容: PHPExcel
第三种方案: 爬虫扒取网页
1.涉及工具:
Facebook主页(以及fb账号,密码)
Puppeteer
(puppeteer是google公司基于Node.js开发的爬虫工具,可以模拟用户的图形界面操作,中文文档: https://zhaoqize.github.io/puppeteer-api-zh_CN/#?product=Puppeteer&version=v1.17.0&show=api-event-response)
2. 逻辑流程(操作步骤):
1)Puppeteer模拟用户登录 =>
2)手动复制fb的cookie信息,并写入文件 =>
3)模拟登录前先将cookie写入fb网站 =>
4)根据fb网页流程到达指定页面 =>
5)通过puppeteer读取dom信息,并写入文件/数据库
3.遇到的问题&解决方案:
1) 问题一: fb对操作频繁的账号/IP是否有安全策略限制?
答:是的,fb的确做了这方面的限制,操作频繁的账号容易被封账号/被封IP; 切记先把cookie信息存入文件中,登录前使用本地文件存储的cookie; 建议在国内某些网站上先完成写入cookie的操作,然后再开发,万一账号被封,国内申诉相对要简单一些
**友情提示: 可提前添加3个以上好友,封号时用以申诉,新账号频繁特别容易被封;
2)问题一:cookie有效期,以及cookie相关的安全策略
答:
A) fb的cookie有效期,好像是25个小时(可自行求证)
B) fb网站的cookie信息无法使用document.cookie等js方法获取,可采用手动复制调试窗口的cookie信息,并存入本地文件中,毕竟cookie有效期在一天左右,一天只需要做一次cookie存储
3) 问题三: fb网页还有哪些安全策略限制,
答:
A)策略限制: fb网站出现弹窗提示,同时让页面被阴影页面覆盖,无法继续操作
B)解决方案:
a)方案一:本来想使用puppeteer图形界面操作,通过获取指定的网页像素坐标,执行puppeteer的鼠标点击事件,但是遗憾没有解决
b)方案二: 通过设置浏览器的设置,禁止网站弹窗弹出,但是puppeteer是基于Node.js运行的,每次执行代码,Node.js会自动创建进程,打开一个浏览器,浏览器配置无法生效
c)方案三: puppeteer操作dom元素,直接使得阴影页面失效style:display=none [有效]
4.注意事项:
1) cookie有效期,好像是25个小时
2) 切记要设置cookie写入,否则容易被封账号,被封IP,可提前添加3个以上好友,封号时用以申诉,新账号频繁特别容易被封
3) fb的网页技术限制,如cookie不能读取,网站弹窗提示无法关闭导致操作流程中断
5.小结:
1)优点: 可获取fb网站的所有参数;
2)缺点: 需解决fb的网页策略限制,而且受fb网站操作流程影响,即需要实时跟进fb网站流程)
注意事项(**坑)
总结
三种方案对比(技术/产品角度, 学习成本,开发周期,人力,个人收获)
上面说了这么多,可能有点晕了,现在再总结对比一下三种方案:主要从技术/产品角度
1. 第一种方案
1)技术角度:接口数据权威,操作可控性强,需熟悉时间研究Graph-SDK,但对于后续应用开发上手会很快
2)产品角度:用户操作少,体验好,但是致命伤害是统计结果不完整(facebook的隐私保护和版权限制,经过粗略统计,大概有1/3的视频数据因视频内容涉及版权问题)
2. 第二种方案:
1)技术角度:操作比较简单,不需要花时间熟悉Graph-SDK,也不需要花时间学习Puppeteer,主需要会简单操作PHPExcel等第三方类库,进行简单的xls文件读取
2)产品角度:用户体验适中(相对于第一种和第三种方案),开发周期最短,能很快上线功能
3. 第三种方案:
1)技术角度: 后端而言(本人PHPer),puppeteer是基于Node.js,需要时间学习接触新的东西,但是puppeteer操作流程比较简单(与用户界面操作一致),但可能因网站安全策略限制导致执行中断;随facebook网站用户操作流程变化而变化,需定期进行调整
2)产品角度: 用户体验不好(需通过puppeteer用户的明文账号密码模拟用户登录行为),数据完整,统计结果准确,
4. 建议: *** 所以最终我采用的是第二种方案(excel数据导出导入),综合技术层面和产品层面,以及开发效率而言,第二种方案是最优的
结语
1. 因为三种方案分别涉及不同的技术工具,牵扯的代码片段和细节较多,为了不影响读者了解本次逻辑流程,我会另外写三篇博客来介绍各自的技术工具,以及相关细节和demo
2.希望我这段时间的经历可以对大家有所帮助,欢迎提出不同见解,有遗漏之处还望指出,谢谢