PHP的file_get_contents不支持gzip编码过的页面?
1、解决方法,找个ungzip的函数来转换下
2、给你的url加个前缀,这样调用
[quote]$content = file_get_contents("compress.zlib://".$url);[/quote]
无论页面是否经过gzip压缩,上述代码都可以正常工作!
PHP 4.3.0以后版本支持,还可以用于fopen之类的函数~!
解决方法来源于:《解决X200声卡(conexant 20561)XP下不能QQ语音的问题》,原文地址:http://www.thinkpad.cn/forum/viewthread.php?tid=1078018&page=1(需要登录论坛才能看到内容)
即使是最新的X200声卡驱动依然有这个问题,解决方法是用东芝Satellite M300系列笔记本的XP声卡驱动代替原有驱动,下载地址为http://pcdrivers.toshiba.com.cn/upload/Satellite/M300/Conexant_Sound_Driver_V3.47.1.50.ZIP,解压后修改TE1HER5a.inf文件的[Conexant]段,在最后加一行[quote]%HdAudioFunctionDriver.Hermosa5051.DeviceDesc% = HdAudModel,HDAUDIO\FUNC_01&VEN_14F1&DEV_5051&SUBSYS_17AA20FF[/quote]
安装更新即可。
无为而为 说两句:原文地址:http://www.cddfwx.org/localdoc/imgcd/webcdfood.aspx?cid=7818
偶然发现,共享。。。
互联网视频网站已经成为大家娱乐不可缺少的一部分,博客、微博、SNS都在大量的转发视频链接,如何在用户粘贴的视频网站链接后面增加对应视频的截图显示呢?这里提供我的解决思路和片段PHP代码。
1、如何在文本中获得URL?
获得诸如“http://www.xxx.com/.....”的URL地址,这个可以使用正则式来解决,执行后$urls就是输入$text字符串中找到的全部URL组成的一维数组:
[quote] preg_match_all("/(http:\/\/[a-z0-9:;&#@=_~%\?\/\.\,\+\-]+)/i", $text, $matches);
$urls = $matches[0];[/quote]
2、如何还原短链接?
在转发中,很多链接都被转换成了短链接,例如视频地址http://www.tudou.com/programs/view/K2xBz5JFBdY/在在转发中被转换成了短地址http://t.cn/hghgjz,一般主要是为了微博节省文字的长度。常见的方法是调用对应短地址的API,还原得到长地址,但是各个短地址提供的方法不一样。短地址实际就是在访问过程中,使用了HTTP 301跳转(Permanently Moved),会在返回的HTTP头中带上真实的地址,使得浏览器可以跳转,这样的话,我们就可以模拟浏览器获得原始地址即可。
片段代码如下,其中$s_url是短地址,$l_url是还原的原始长地址:
[quote]$SHORT_URL = array (
"t.cn",
"url.cn",
"tinyurl.com",
"goo.gl",
......
);
//检查是否是短地址
$found = false;
foreach ($SHORT_URL as $v)
{
$pattern = "/{$v}/i";
if (preg_match($pattern, $s_url, $ret) == 1)
{
$found = true;
break;
}
}
if (!$found)
{
//不是短地址,直接返回
$l_url = $s_url;
}
else
{
//模拟HTTP访问,还原短地址
$u = parse_url($s_url);
$host_ip = gethostbyname($u["host"]);
$host_port = 80;
$request_header = "";
$request_header .= "GET {$u['path']} HTTP/1.1\r\n";
$request_header .= "Host:{$u['host']}\r\n";
$request_header .= "User-Agent: Mozilla/5.0\r\n";
$request_header .= "Accept: */*\r\n";
$request_header .= "Cache-Control: no-cache\r\n";
$request_header .= "Connection: Close\r\n";
$request_header .= "\r\n";
$request_header .= "\r\n";
$fh = fsockopen($host_ip, $host_port);
fputs($fh, $request_header);
$response = "";
while(!feof($fh))
{
$response .= fread($fh, 1);
}
fclose($fh);
if (preg_match("/Location:(.*?)\r\n/i", $response, $ret) != 0)
{
$l_url = rtrim(ltrim($ret[1]));
}
}[/quote]
3、如何获取原始视频链接对应视频的截图?
常见的视频网站在视频播放页面的源码中都会有对应截图的URL地址,我们只需要打开视频地址,分析源码获取即可,这个就没有统一的方法来实现,例如土豆tudou的视频播放页面源码中看到类似“,thumbnail = 'http://i3.tdimg.com/080/946/236/p.jpg'”的这样一行,这个就是视频对应的截图地址。
片段代码如下,其中$url是视频网站地址,$img_url是对应截图URL地址:
[quote]//构建各个视频网站的截图地址分析正则式,这个需要根据不同网站的情况设定
$VIDEO_SITE = array (
"youku.com" => "/\+0800\|(.*?)\|\">/i",
"ku6.com" => "/<span class=\"s_pic\">(.*?)<\/span>/i",
"tudou.com" => "/thumbnail = '(.*?)'/i",
"56.com" => "/\"img\":\"(.*?)\"/i",
"video.sina.com.cn" => "/pic: '(.*?)'/i",
......
);
//检查是否是视频网站地址
$pattern_img = "";
foreach ($VIDEO_SITE as $k => $v)
{
$pattern_site = "/{$k}/i";
if (preg_match($pattern_site, $url, $ret) == 1)
{
$pattern_img = $v;
break;
}
}
//获得网页源码,分析截图URL
$content = file_get_contents($url);
preg_match($pattern_img, $content, $ret);
$img_url = $ret[1];[/quote]
最后,由于我们需要连接获取的数据的短地址和视频网站可能访问速度不快,如果有大量重复的URL要处理(例如“我的微博”,展现的是最新20条,所以在一定时间内反复访问的也就是这20条中的URL),所以可以考虑自己做本地缓存,我是采用将短地址和长地址、视频地址和截图地址的对应关系作为二维数组保存,然后serialize保存到缓冲文件,同时考虑了缓冲过期(我设定为7天)删除的刷法,以免累计的旧数据太多,这里就不详细写了。
OK,打完,收工~~~!
引子:xajax是一个开源的PHP类库,它能够让你黏合HTML、CSS、Javascrīpt和PHP,轻而易举的开发功能强大、基于WEB的AJAX应用软件. 使用xajax开发的应用软件,无需重新调入页面,就能够异步调用服务器端的PHP函数和更新内容。
xajax具体的用法不说了,直接说问题:想做一个页面的刷新效果,在获取数据过程中提示用户“正在获取数据”,数据获取完毕后,再将提示语替换成实际的数据,很简单,用xajax做两个PHP函数:
[quote]function show_loading()
{
...
$objResponse->assign("my_text", "innerHTML", "正在获取数据");
...
}
function show_data()
{
...
获取数据$data
$objResponse->assign("my_text", "innerHTML", $data);
...
}[/quote]
再用JavaScript调用
[quote]xajax_show_loading();
xajax_show_data();[/quote]
测试发现,大多数情况,都可以得到想要的结果,但是偶尔会出现一直是“正在获取数据”,无法展现数据的问题。检查发现这种情况数据是获取成功的,进一步debug发现是由于先调用的函数不一定先执行造成的,也就是show_data成功展示了数据,但又被执行较慢的show_loading用“正在获取数据”覆盖了本该显示数据,导致看起来像是获取数据失败,执行出错或卡死的感觉。
最初用了个笨办法,延缓获取数据和展示的行为,JavaScript改为
[quote]xajax_show_loading();
setTimeout(xajax_show_data(), 200);[/quote]
也能达到效果,但是方法很撮。。。
最后翻了xajax的文档,发现可以call或者script调用JavaScript,于是改为
[quote]function show_data()
{
...
$objResponse->assign("my_text", "innerHTML", "正在获取数据");
$objResponse->script("xajax_update_data()");
...
}
function update_data()
{
...
获取数据$data
$objResponse->assign("my_text", "innerHTML", $data);
...
}[/quote]
JavaScript改为
[quote]xajax_show_data();[/quote]
这样就可以确保先执行show_data更新等待提示语完成后,再执行update_data展现数据了。解决~~!
微博大道而行,我也得跟上:
1、顶部栏目新增“我的微博”,自动采集最新20条,来源有我的新浪微博和腾讯微博,抓取的缓冲时间为300秒;腾讯微博抓取偶尔有“check sign error”错误,略不稳定,不知是腾讯接口问题,还是偶对oauth_signature的算法实现有问题,待观察
2、左侧栏目增加微博入口
鉴于微博口水较多,暂不加入RSS输出,酱紫~~~
写这个页面的时候,粗略看了“腾讯微博开放平台”和“新浪微博开放平台”API文档中OAuth和timeline的一些描述、范例和接口说明,前者的文档需要努力呀,大小写错误、描述不清晰等问题较多。
---------------以下 2011年5月5日补充------------------
“腾讯微博抓取偶尔有“check sign error”错误”,这个问题找到了,是由于生成的oauth_signature拼装到url的时候,没有做urlencode,当其中包含+字符的时候,参数传递就会出现问题;其他参数也忘记了,一并加上。
附:以调用腾讯“broadcast_timeline 我发表时间线”为例的PHP片段代码,主要为了说明oauth_signature的生成和url的拼装,其中考虑有同名参数时需再按value排序(If two or more parameters share the same name, they are sorted by their value):
[quote]$QQ_APP_KEY = "xxx";
$QQ_APP_SECRET = "xxx";
$QQ_AUTH_TOKEN = "xxx"; //Request Token
$QQ_TOKEN_SECRET = "xxx"; //Request Token Secret
$QQ_BROADCAST_TIMELINE_URL = "http://open.t.qq.com/api/statuses/broadcast_timeline";
$QQ_HTTP_METHOD = "GET";
$QQ_DEFAULT_COUNT_NUMBER = 20;
$QQ_BROADCAST_TIMELINE_PARAMS = array (
"format" => "json",
"oauth_consumer_key" => $QQ_APP_KEY,
"oauth_signature_method" => "HMAC-SHA1",
"oauth_token" => $QQ_AUTH_TOKEN,
"oauth_version" => "1.0",
"pageflag" => 0,
"pagetime" => 0,
"reqnum" => $QQ_DEFAULT_COUNT_NUMBER,
"oauth_timestamp" => "",
"oauth_nonce" => ""
);
//init variable params
$QQ_BROADCAST_TIMELINE_PARAMS["oauth_timestamp"] = time();
$QQ_BROADCAST_TIMELINE_PARAMS["oauth_nonce"] = md5(uniqid(rand()));
//sort params: If two or more parameters share the same name, they are sorted by their value
ksort($QQ_BROADCAST_TIMELINE_PARAMS);
foreach ($QQ_BROADCAST_TIMELINE_PARAMS as $k => $v)
{
if (is_array($v))
{
sort($v);
$QQ_BROADCAST_TIMELINE_PARAMS[$k] = $v;
}
}
$params = "";
foreach ($QQ_BROADCAST_TIMELINE_PARAMS as $k => $v)
{
if (is_array($v))
{
foreach ($v as $k2 => $v2)
{
$params .= urlencode($k)."%3D".urlencode($v2)."%26";
}
}
else
{
$params .= urlencode($k)."%3D".urlencode($v)."%26";
}
}
$params = substr($params, 0, strlen($params) - 3);
//generate signature base string, key and oauth signature
$signature_base = $QQ_HTTP_METHOD."&".urlencode(strtolower($QQ_BROADCAST_TIMELINE_URL))."&".$params;
$signature_key = $QQ_APP_SECRET."&".$QQ_TOKEN_SECRET;
$oauth_signature = base64_encode(hash_hmac("sha1", $signature_base, $signature_key, true));
//generate full request url
$url = $QQ_BROADCAST_TIMELINE_URL."?";
foreach ($QQ_BROADCAST_TIMELINE_PARAMS as $k => $v)
{
if (is_array($v))
{
foreach ($v as $k2 => $v2)
{
$url .= urlencode($k)."=".urlencode($v2)."&";
}
}
else
{
$url .= urlencode($k)."=".urlencode($v)."&";
}
}
$url .= "oauth_signature=".urlencode($oauth_signature);
//get remote data by url
...
[/quote]
无为而为 说两句:发件人 Google Apps Team
Google App超过10用户要收费咯,老用户不受影响。