访客身份抓取新浪微博视频。Sina Visitor System
程序员文章站
2022-03-25 13:29:24
...
最近要抓取写新浪微博的视频。怎知新浪微博(几乎)整站都启用了Sina Visitor System系统。即使无需登录就能访问的页面,也需要获得一个访客cookie才能访问。翻了下百度几乎都是模拟登录来抓取数据的。可我不需要那么复杂,于是就自己干了。
先清除了浏览器cookie 模拟下访问我要抓取的视频 http://weibo.com/tv/v/Fs7ztjjfL?from=vhot。Fiddler截图如下。大致分了一下几部。
1.访问 genvisitor 获取一个tid.
2.用tid 先获取一个 cookie,同时得到2个参数 sub subp。3.带着获得的cookie,和sub subp 2个参数 获得第二个cookie。
4.最后用第二个cookie访问要抓取的页面。
其实 新浪的访客系统的源文件已经写的很清楚如何获得访客身份了。如图
最后贴下代码:
<?php
class Vgather extends base {
/**
*
* 由于weibo防爬虫需要获得访客身份cookie后在访问,大致流程如下。
* 获得tid->请求一个访客cookie->请求一个跨域cookie->抓去数据。
* @param string $url
* @author maskxu
*/
public function catch_html($url)
{
$this->init_redis();
$ckey = 'gooseeker_weibo_video_cookie';
$xcookie = $this->redis->get($ckey);
//如果redis缓存的cookie过期,重新获取。
if(empty($xcookie))
{
//获得tid
$tid = $this->_get_tid();
$cookie = $this->_get_cookie($tid, $sub, $subp);
if(empty($sub)) //sub 可能会获取失败,原因未知,可能是因为频繁访问.
{
//throw new Exception("Get Sub error", 1);
return false;
}
$xcookie =$this->_get_crosscookie($sub, $subp,$cookie);
$this->redis->set($ckey, $xcookie ,3600*24*7);
$rst = $this->redis->get($ckey);
}
$content = $this->_curl_data($url,"GET","",false,$xcookie,false);
return $content;
}
//获得tid
private function _get_tid()
{
$postdata['cb'] = "gen_callback";
$postdata['fp'] = '{"os":"1","browser":"Chrome61,0,3163,100","fonts":"undefined","screenInfo":"1920*1080*24","plugins":"Portable Document Format::internal-pdf-viewer::Chrome PDF Plugin|::mhjfbmdgcfjbbpaeojofohoefgiehjai::Chrome PDF Viewer|::internal-nacl-plugin::Native Client|Enables Widevine licenses for playback of HTML audio/video content. (version: 1.4.8.1008)::widevinecdmadapter.dll::Widevine Content Decryption Module"}';
$url = "https://passport.weibo.com/visitor/genvisitor";
$content = $this->_curl_data($url,"POST",$postdata);
preg_match('/"tid":"(.*)",/i', $content, $matches);
$tid = $matches[1];
return $tid;
}
//第一次获得cookie. sub,subp,cookie是第二次获得跨域cookie必须的.
private function _get_cookie($tid,&$sub,&$subp)
{
$url = "https://passport.weibo.com/visitor/visitor?";
$url .= 'a=incarnate&t='.urlencode($tid).'&w=2&c=095&gc=&cb=crossdomain&from=weobo&rand=0.'.rand();
$cookie="";
$content = $this->_curl_data($url,"GET","",true,$cookie);
preg_match('/"sub":"(.*)",/i', $content, $matches);
$sub = $matches[1];
preg_match('/"subp":"(.*)"}/i', $content, $matches);
$subp = $matches[1];
return $cookie;
}
//第二次获得跨域xcookie
private function _get_crosscookie($sub, $subp,$cookie)
{
$url = "https://passport.weibo.com/visitor/visitor?";
$url .= 'a=crossdomain&cb=return_back&s='.$sub.'&sp='.$subp.'&w=2&from=weibo&rand=0.'.rand();
$content = $this->_curl_data($url,"GET","",true,$cookie);
return $cookie;
}
private function _curl_data($url,$method="GET",$postdata="",$ssl=false,&$cookie="",$show_header=true )
{
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url );
curl_setopt($ch,CURLOPT_USERAGENT,'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36');//模拟UA
if($show_header)
curl_setopt($ch, CURLOPT_HEADER, 1); //show header 为了拿到cookie
if($method == "POST")
{
curl_setopt($ch,CURLOPT_POST,1);//使用post提交数据
curl_setopt($ch,CURLOPT_POSTFIELDS,$postdata);//设置 post提交的数据
}
if($ssl)
{
// curl_setopt($ch, CURLOPT_SSLVERSION, 3); //设定SSL版本
// 对认证证书来源的检查,0表示阻止对证书的合法性的检查。
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// 从证书中检查SSL加密算法是否存在
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true);
}
if($cookie != "")
{
curl_setopt($ch, CURLOPT_COOKIE, $cookie);
}
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);//关闭直接输出
$data = curl_exec($ch);
if($show_header)
{
preg_match_all('|Set-Cookie: (.*);|U', $data, $results);
if(count($results)>1)
$cookie = implode(';', $results[1]);
}
curl_close($ch);
return $data ;
}
}
?>