blog.Ring.idv.tw

PHP

Universal Text Box - 通用輸入框

Laconica - The Open Microblogging Tool.是一套免費且開放原始碼(PHP)的微型部落格平臺,可以用在一個社群或群組的短訊(140 character)溝通平臺,類似於當下熱門的TwitterPlurk

如果您是Twitter的愛用者,對於「@」符號應該不會太陌生,下述是從Laconica的原始碼抓出它的Regular Expression來看:

import re
msg = "@account This is a test."
p = r'(?:^|\s)@([a-z0-9]{1,64})'
m = re.findall(p,msg)  
for i in m:
    print i

從這個簡單的小程式來看,重點在於「(?:^|\s)@([a-z0-9]{1,64})」這一行Regular Expression,它處理的方式是在「@」之後的「帳號名稱」只能是小寫的字母和數字所組成,且範圍限制在1到64個字元之間,而在「@」之前的處理方式則是必須是訊息的起始位置或是空白字元,不過因為它是用「(?:^|\s)」括弧涵蓋起來,所以加上「?:」來排除這個Group,如此就是一個類似處理Twitter訊息輸入欄的Regular Expression

下述這個範例就是一個簡單的利用「#」符號來擴展成標記Tag的方法:

import re
msg = "Today is a sunny day. #weather #life"
p = r'(?:^|\s)#([A-Za-z0-9_\-\.]{1,64})'
m = re.findall(p,msg)  
for i in m:
    print i

參考資源

8.2. re — Regular expression operations

How @replies work on Twitter (and how they might)

2009-05-12 16:14:57 | Add Comment

Web Scraping for CKIP中文斷詞系統

自然語言處理的研究領域中,「Word Segmentation(斷詞)」是一個相當重要的技術,舉個英文的例子來說:

I like to play baseball.

斷詞後的結果:

I」、「like」、「to」、「play」、「baseball

因為英文字句中的各個單字之間都有著「空隔」來區隔,但中文呢?卻毫無如此的規則可循~

所以利用詞庫的方式是一種解決方案~ 這裡介紹利用「中研院-CKIP中文斷詞系統」來協助我們進行中文的斷詞工作~

雖然你也可以在「中研院-CKIP中文斷詞系統」申請使用~ 不過需要自行撰寫相關的Socket程式並剖析XML資料~

所以本文提供使用Web Scraping的方式來達成~

CKIP.php

<?php
/**
 * Date: 2008/06/06
 * Shen(http://blog.ring.idv.tw)
 */
require_once "HttpClient.php";
class CKIP
{
	private $param = "";
	private $body = "";

	function __construct(){}
	public function setParam($param)
	{
		$this->param = $param;
	}	
	public function doQuery()
	{
		if($this->param != "")
		{
			$uri = "http://mt.iis.sinica.edu.tw/cgi-bin/text.cgi";
			$data = array('query' => $this->param);
			$body = HttpClient::quickPost($uri, $data);

			$regex = '/URL=\'(.*)\'\">/Us';
			preg_match($regex,$body,$match);
			$redirect = "http://mt.iis.sinica.edu.tw/" . $match[1];
			$body = HttpClient::quickGet($redirect);
	
			$regex = '/HREF=(.*)>/Us';
			preg_match($regex,$body,$match);
			$filename = str_replace(".txt", ".tag.txt", $match[1]);
			$redirect = "http://mt.iis.sinica.edu.tw/uwextract/pool/" . $filename;
			$this->body = HttpClient::quickGet($redirect);

			return true;
		}
		return false;
	}
	public function getBody()
	{
		return $this->body;
	}
}
?>

Demo

<?php
require_once "CKIP.php";
$ckip = new CKIP();
$ckip->setParam("這個東西不錯吃!");
$ckip->doQuery();
$body = $ckip->getBody();
$body = iconv("Big5","UTF-8",$body);
echo $body;
?>

2008-06-06 19:40:32 | Comments (3)

取得MediaWiki Editable Text - MediaWiki API

取得MediaWiki Editable Text.這是先前利用Web Scraping的方式取得MediaWiki Editable Text的作法,然而現在有更好的方式來完成這樣的工作~

我們目前可以透過「MediaWiki API」來協助我們做這樣的事項~

<?php
require_once "HttpClient.php";
if($_GET)
{
	$sentence = $_GET['input'];
	$uri = "http://en.wikipedia.org/w/api.php?action=query&prop=revisions&titles=$sentence&rvprop=content&format=php";
	$body = HttpClient::quickGet($uri);

	$body = unserialize($body);
	$body = array_pop($k["query"]["pages"]);
	echo $body["revisions"][0]["*"];
}

API的時代果然來臨了...

2008-05-12 15:05:12 | Add Comment

Web Scraping for Yahoo!生活+

在自然語言處理的領域中,有愈來愈多直接將網路資料當做語料庫(Corpus)來使用的趨勢~ 而要達成這樣的應用,當然需要有一個類似Web Crawler的機器人程式~ 來幫我們進行前置的搜集作業~ 而本文就是要做一個這樣的應用~ 這裡以「Yahoo!生活+」當做例子~

底下程式您可以自由地更改及使用~ 如果您有為它加上些許功能,也歡迎您貢獻您的成果 ^^

WebScraping.php

<?php
/**
 * Date: 2008/04/26
 * Shen(http://blog.ring.idv.tw)
 */
interface WebScraping
{
	public function doQuery();
	public function getBody();
}
?>

YahooLife.php

<?php
/**
 * Date: 2008/04/26
 * Shen(http://blog.ring.idv.tw)
 */
require_once "HttpClient.php";
require_once "WebScraping.php";

class YahooLife implements WebScraping
{
	private $param = "";
	private $body = "";
	
	function __construct(){}
	public function setKeyword($keyword)
	{
		$this->param = urlencode($keyword);
	}
	public function doQuery()
	{
		if($this->param != "")
		{
			$body = HttpClient::quickGet('http://twsearch.lifestyle.yahoo.com/search?cate=store&type=biz&p=' . $this->param);
			$body = str_replace("<em>",'',$body);
			$body = str_replace("</em>",'',$body);
			$this->body = $body;
			return true;
		}
		return false;
	}
	public function getBody()
	{
		return $this->body;
	}
	public function getStoreAddress()
	{
		$regex = '/<address>(.*)<\/address>/Us';
		preg_match_all($regex,$this->body,$match);
		return $match[1];
	}
	public function getSatisfaction()
	{
		$regex = '/<img src=\"http:\/\/tw.yimg.com\/i\/tw\/lifestyle\/icon_star0(.*).gif/Us';
		preg_match_all($regex,$this->body,$match);
		return $match[1];
	}
	public function getStoreID()
	{
		$regex = '/http:\/\/tw.wrs.yahoo.com\/\*\*http%3A%2F%2Ftw.lifestyle.yahoo.com%2Fbiz.html%3Fbizid%3D(.*)\">/Us';
		preg_match_all($regex,$this->body,$match);
		return $match[1];	
	}
}
?>

YahooStore.php

<?php
/**
 * Date: 2008/04/26
 * Shen(http://blog.ring.idv.tw)
 */
require_once "HttpClient.php";
require_once "WebScraping.php";

class YahooStore implements WebScraping
{
	private $storeId = "";
	private $body = "";
	
	function __construct(){}
	public function setStoreID($id)
	{
		$this->storeId = $id;
	}
	public function doQuery()
	{
		if($this->storeId != "")
		{
			$body = HttpClient::quickGet("http://tw.lifestyle.yahoo.com/biz_comment.html?bizid=" . $this->storeId . "&psm=");
			$this->body = $body;
			return true;
		}
		return false;
	}
	public function getBody()
	{
		return $this->body;
	}
	public function getStoreComments()
	{
		$regex = '/<blockquote>(.*)<\/blockquote>/Us';
		preg_match_all($regex,$this->body,$match);
		return $match[1];
	}
	public function getSatisfaction()
	{
		$regex = '/<img src=\"http:\/\/tw.yimg.com\/i\/tw\/lifestyle\/icon_star0(.*).gif/Us';
		preg_match_all($regex,$this->body,$match);
		return $match[1];
	}
}
?>

測試範例

<?
require_once "YahooLife.php";
require_once "YahooStore.php";

$Ylife = new YahooLife();
$Ylife->setKeyword("美食");
$Ylife->doQuery();
$address = $Ylife->getStoreAddress();
echo "<h2>商家地址</h2>";
show($address);

$satisfaction = $Ylife->getSatisfaction();
echo "<h2>商家滿意度</h2>";
show($satisfaction);

$storeid = $Ylife->getStoreID();
echo "<h2>商家ID</h2>";
show($storeid);

// sleep for 2 seconds
sleep(2);

$Ystore = new YahooStore();
$Ystore->setStoreID($storeid[1]);
$Ystore->doQuery();

$comments = $Ystore->getStoreComments();
echo "<h2>商家評價意見</h2>";
show($comments);

$satisfaction = $Ystore->getSatisfaction();
echo "<h2>商家評價滿意度</h2>";
show($satisfaction);

function show($value)
{
	foreach($value as $v)
		echo $v . "<br/>";	
}
?>

取得原始碼

2008-04-26 21:11:47 | Add Comment

寫一個Hello World的PHP Extension

Java中我們可以透過JNI的方式來進行和C語言的溝通~ 而這不外乎要遵循一些共通的介面來達到~ 當然PHP也是如此~ 有興趣的話可以看看「PHP Source Code/ext」底下的一些extension,像是PDOGD等等~ 都是這樣達成的~

所以像Youtube這樣用PHP寫成的網站還要結合後端轉檔程式該怎麼做呢?

由於筆者不是Youtube的工程師~ 恕無法提供正解~ XD

不過若要比較「完善」地結合像FFmpeg這樣的函式庫~ 那採用寫一個PHP Extension的方式倒是不錯的解決方案~

所以本文主要的訴求就在於開發一個屬於自己的Hello World的PHP Extension。

hello.c

#include "php.h"

ZEND_FUNCTION(hello);
zend_function_entry hellomodule_functions[] =
{
    ZEND_FE(hello, NULL)
    {NULL, NULL, NULL}
};
zend_module_entry hellomodule_module_entry =
{
    STANDARD_MODULE_HEADER,
    "Hello Module",
    hellomodule_functions,
    NULL, 
    NULL, 
    NULL, 
    NULL, 
    NULL,
    NO_VERSION_YET,
    STANDARD_MODULE_PROPERTIES
};

#if COMPILE_DL_FIRST_MODULE
ZEND_GET_MODULE(hellomodule)
#endif

ZEND_FUNCTION(hello)
{
	RETURN_STRING("HELLO WORLD",1);
}

Compiling

先進行編譯處理~

gcc -fpic -DCOMPILE_DL_FIRST_MODULE=1 -I/usr/local/include -I. -I/usr/include/php5 -I/usr/include/php5/Zend -I/usr/include/php5//main -I/usr/include/php5/TSRM -c -o hello.o hello.c

Linking

然後產生一個Shared Object~

gcc -shared -L/usr/local/lib -rdynamic -o hello.so hello.o

掛上hello module

cp hello.so /usr/lib/php5/20060613+lfs/

修改「php.ini」,加上「extension=hello.so]~ 然後重新啟動您的Apache Server

vi /etc/php5/apache2/php.ini
/etc/init.d/apache2 restart

最後用「phpinfo()」來驗證是否已掛上自己的Extension~ 成功的話會看到下圖:

測試HelloWorld

<?php
echo hello();
?>

看到畫面出現「HELLO WORLD」就成功啦! ^^

不過如果您不想那麼麻煩的掛載extension,也可以考慮用「dl()」來動態載入達成~

相關細節可以參考下述資源~

參考資源

PHP: Creating Extensions - Manual

PHP: Source Discussion - Manual

Extension Writing - devzone.zend.com

類似文章

用Java來和C做溝通的介面 - JNI

2008-04-25 21:28:18 | Comments (9)

Previous Posts
Copyright (C) Ching-Shen Chen. All rights reserved.

::: 搜尋 :::

::: 分類 :::

::: 最新文章 :::

::: 最新回應 :::

::: 訂閱 :::

Atom feed
Atom Comment