PHPでスクレイピング&本文抽出をする方法・ライブラリ

引用する記事のタイトル&本文の抜粋を取得したい!

ということで、PHPスクレイピング&本文抽出する方法を調べてみました。

[amazonjs asin=“4839956472” locale=“JP” title=“実践 Webスクレイピング&クローリング-オープンデータ時代の収集・整形テクニック”]

本文抽出に使用するライブラリ

いろいろと選択肢はあったのですが、今回はfivefilters.orgPHP Readabilityを使ってみることにしました。

BitBucketのPHP Readabilityのレポジトリのものより、同じfivefilters.orgのFull-Text RSSレポジトリに使われているPHP Readabilityのほうが新しいっぽいのでこっちを使います。

ちなみにFull-Text RSS最新版のダウンロードは有償ですが、古いバージョンは無料で利用できます。また、APIの提供などもされているようなので気になる人は公式サイトをチェックしてみてください。

git cloneして、libraries / readability を好きなディレクトリに移動します。

$ git clone https://bitbucket.org/fivefilters/full-text-rss.git

PHP Readabilityの使い方

PHP Readabilityの使い方は簡単で、Readability.phpをrequireしてnew Readability($html, $url)とするだけです。


require_once '/PathToLibrary/readability/Readability.php';

//取得する記事URLを指定
$url = 'http://web-tsukuru.com/270';

//URLからHTMLを取得してUTF8にエンコーディング
$html = file_get_contents($url);
$html = mb_convert_encoding($html, "UTF-8", "ASCII,JIS,UTF-8,EUC-JP,SJIS" );

//tidy_parse_stringが使用可能であれば、
//tidy::cleanRepairでHTMLの誤りなどを修正
if (function_exists('tidy_parse_string')) {
  $tidy = tidy_parse_string($html, array(), 'UTF8');
  $tidy->cleanRepair();
  $html = $tidy->value;
}

//Readabilityを初期化
$readability = new Readability($html, $url);
$result = $readability->init();

if ( empty($result) ) return false;

//タイトルを取得
$title =  $readability->getTitle()->textContent;

//記事本文を取得
$content = $readability->getContent()->innerHTML;

//再度、tidy_parse_stringを使用
if (function_exists('tidy_parse_string')) {
  $tidy = tidy_parse_string($content, array('indent'=>true, 'show-body-only' => true), 'UTF8');
  $tidy->cleanRepair();
  $content = $tidy->value;
}

タイトルの取得は、

$title =  $readability->getTitle()->textContent;

記事本文の取得は、

$content = $readability->getContent()->innerHTML;

のようにできます。

記事本文はHTMLをそのまま取得しているので、strip_tags()などでHTMLを除去すると良さそうです。

そのほかのPHPで本文抽出する方法

有名なReadabilityは本文抽出に使えるAPIを非商用で提供しているみたいです。APIだと提供終了する可能性があるので、ちょっと微妙ですが軽く使ってみるには良さそうですね。

Readability Developer APIs

そのほか、今回は使ってないですが以下のようなライブラリがあるみたいです。 https://github.com/scotteh/php-goose https://github.com/essence/essence

また、Quoraに投げられた「HTMLから本文抽出する一番の方法は?」という質問も参考になります。

Quora | What’s the best method to extract article text from HTML documents?

PHP以外だとJavaのboilerpipeあたりが有名みたいです。

Mecabにユーザー辞書を導入する(はてな、Wikipedia、ニコニコ大百科など)

MecabはてなキーワードWikipediaニコニコ大百科などを元にしたユーザー辞書を追加します。公式マニュアルはこちら

ユーザー辞書を追加する流れは、

1.元データを取得してCSVファイルに変換 2.CSVファイルを辞書ファイルにコンパイル 3.Mecabの設定ファイルに追加

となります。

[amazonjs asin=“489476654X” locale=“JP” title=“Rで学ぶ日本語テキストマイニング”]

1.元データを取得してCSVを作成

今回は、例としてはてなキーワードを追加します。

まずは元データを取得します。

$ wget http://d.hatena.ne.jp/images/keyword/keywordlist_furigana.csv

次に「mecabにはてなキーワードのタイトルリストを追加する」を参考に以下のPHPスクリプトを実行してMecabのユーザー辞書用CSVファイルを作成します。

 $v) {
        if (preg_match("/[\",\n]/", $v)) {
            $data[$k] = '"' . str_replace('"', '""', $v) . '"';
        }
    }
    $line = implode(',', $data);
    return $line;
}

//インポート元CSVとエクスポート先CSVを引数に指定
make_csv("keywordlist_furigana.csv","hatena.csv");

なおニコニコ大百科Wikipediaについては、以下のサイトの通りすれば追加できると思います。

ニコニコ大百科データからMeCab辞書を生成する mecabにwikipediaのタイトルリストを追加する

2.CSVからユーザー辞書を作成

下記のコマンドを実行して、csvファイルからユーザー辞書ファイル(.dic)にコンパイルします。

$ /usr/local/libexec/mecab/mecab-dict-index -d/usr/local/lib/mecab/dic/ipadic -u 辞書名.dic -f utf-8 -t utf-8 インポート元.csv

以下のコマンドで辞書を指定してmecabが使えれば問題なくコンパイルできています。

$ mecab -u 辞書名.dic

3.辞書をユーザー辞書として登録

任意のディレクトリに作成した辞書名.dicを移動します。今回は/usr/local/lib/mecab/dicにuserを作成して移動します。

$ mkdir /usr/local/lib/mecab/dic/user
$ mv 辞書名.dic /usr/local/lib/mecab/dic/user/辞書名.dic

/usr/local/lib/mecab/dic/ipadic/dicrc もしくは /usr/local/etc/mecabrc に以下を追加します。

userdic = /usr/local/lib/mecab/dic/user/辞書名.dic

これで完了です!

Mecabなど形態素解析で使うIPA品詞体系(品詞ID|pos-id)

Mecab茶筅など形態素解析で使う辞書のIPA品詞体系をまとめてみました。

Mecabでは::getPosId()で品詞IDを取得できます。

[amazonjs asin=“4873114705” locale=“JP” title=“入門 自然言語処理”]

IPA品詞体系

品詞ID 分類 説明
0 その他,間投 「あ」「ア」のみ 「そんなぁ」
1 フィラー 「えーと」「なんか」など
2 感動詞 「うむ」「お疲れさま」「トホホ」
3 記号,アルファベット 「A-z」
4 記号,一般 「?」「!」「¥」
5 記号,括弧開 「(」「【」など
6 記号,括弧閉 「 )」「】」など
7 記号,句点 「。」「.」のみ
8 記号,空白 「 」のみ
9 記号,読点 「、」「,」のみ
10 形容詞,自立 「美しい」「楽しい」
11 形容詞,接尾 「ったらしい」「っぽい」
12 形容詞,非自立 「づらい」「がたい」「よい」 「見づらい」
13 助詞,格助詞,一般 「の」「から」「を」
14 助詞,格助詞,引用 「と」のみ
15 助詞,格助詞,連語 「について」「とかいう」
16 助詞,係助詞 「は」「こそ」「も」「や」
17 助詞,終助詞 「かしら」「ぞ」「っけ」「わい」
18 助詞,接続助詞 「て」「つつ」「および」「ので」
19 助詞,特殊 「かな」「けむ」「にゃ」
20 助詞,副詞化 「と」「に」のみ
21 助詞,副助詞 「くらい」「なんか」「ばっかり」
22 助詞,副助詞/並立助詞/終助詞 「か」のみ
23 助詞,並立助詞 「とか」「だの」「やら」
24 助詞,連体化 「の」のみ
25 助動詞 「ます」「らしい」「です」
26 接続詞 「だから」「しかし」
27 接頭詞,形容詞接続 「お」「まっ」 「お高い」「まっ赤」
28 接頭詞,数接続 「計」「毎分」 数値に接続するもの
29 接頭詞,動詞接続 「ぶっ」「引き」 動詞に接続するもの。「ぶったたく」
30 接頭詞,名詞接続 「最」「総」 名詞に接続するもの。「最高値」
31 動詞,自立 「投げる」
32 動詞,接尾 「しまう」「ちゃう」「願う」 「行ってしまう」
33 動詞,非自立 「しまう」「ちゃう」「願う」 「行ってしまう」「やっちゃったね」「ご遠慮願う」
34 副詞,一般 「あいかわらず」「多分」 必ず後ろで切れるもの,連体修飾が不可能なもの
35 副詞,助詞類接続 「こんなに」「そんなに」 「する」「だ」などが後続可能な副詞.
36 名詞,サ変接続 「インプット」「悪化」 後ろに「する」「できる」などがつくもの
37 名詞,ナイ形容詞語幹 「申し訳」「仕方」 助動詞「ない」の直前に現れる名詞
38 名詞,一般 「テーブル」 通名詞。
39 名詞,引用文字列 「いわく」のみ
40 名詞,形容動詞語幹 「健康」「安易」「駄目」 形容動詞語幹で「な」の前に現れるもの
41 名詞,固有名詞,一般 一般的な固有名詞
42 名詞,固有名詞,人名,一般 一般的な人名。
43 名詞,固有名詞,人名,姓 一般的な日本人の性。
44 名詞,固有名詞,人名,名 一般的な日本人の名。
45 名詞,固有名詞,組織 「株式会社◯◯」 組織を表す。
46 名詞,固有名詞,地域,一般 「東京」 国以外の地名。
47 名詞,固有名詞,地域,国 「日本」 国名。
48 名詞,数 「0」「一」 数字及び「何(回)」など。
49 名詞,接続詞的 「◯対◯」「◯兼◯」 単語と単語を接続するもの。
50 名詞,接尾,サ変接続 「(可視)化」 後ろに「する」がつく接尾語。
51 名詞,接尾,一般 「感」「観」「性」 複合名詞をつくるもの。
52 名詞,接尾,形容動詞語幹 「的」「げ」「がち」
53 名詞,接尾,助数詞 「個」「つ」「本」「冊」
参考:
ipadic version 2.7.0 ユーザーズマニュアル (*PDF)
形態素解析ツールの品詞体系

初心者がvimをカスタマイズしてプラグインを導入するまで

vimをアップデート

vimのバージョンが古くて一部のプラグインが使えなかったので、新しいバージョンのvimをインストールします。 ついでにneocompleteなどで使うので、Luaも有効化しておきます。

$ yum -y install mercurial
$ yum -y install ncurses-devel
$ cd /usr/local/src
$ hg clone https://vim.googlecode.com/hg/ vim
$ cd /usr/local/src/vim
$ ./configure --enable-multibyte --with-features=huge --disable-selinux --prefix=/usr/local --enable-luainterp=dynamic --enable-rubyinterp --enable-fail-if-missing --with-lua-prefix=/usr
$ make
$ make install

そのあとに、シンボリックリンクを貼るか.bashrcにaliasを設定します。

$ vi ~/.bashrc

以下のaliasを追記。vimまたはviで新しくインストールしたvimが起動します。

alias vi='/usr/local/bin/vim'
alias vim='/usr/local/bin/vim'
alias vimrc='vi /usr/local/share/vim/vimrc'

.bashrcに追記した内容を反映させます。

$ bash

ミニマムの設定をvimrcに追加

設定ファイルvimrcの場所を確認します。

$ vim --version

すると、vimのバージョンなどと一緒に設定ファイルの場所が以下のように表示されます。

システム vimrc: "/$VIM/vimrc"
ユーザ vimrc: "$HOME/.vimrc"

$VIMなどはvim上で:echo $VIMで確認できます。

とりあえず、下記を調べた設定ファイルvimrcに追加します。

set number
set title
set ambiwidth=double
set tabstop=4
set expandtab
set shiftwidth=4
set smartindent
set list
set listchars=tab:»-,trail:-,eol:↲,extends:»,precedes:«,nbsp:%
set nrformats-=octal
set hidden
set history=50
set virtualedit=block
set whichwrap=b,s,[,],<,>
set backspace=indent,eol,start
set wildmenu
syntax on

カラースキームを設定

次にカラースキームを設定します。今回は人気のmolokaiを設定します。 *colorsディレクトリの場所は環境に合わせて確認してください

$ cd /usr/local/share/vim/vim74/colors
$ git clone https://github.com/tomasr/molokai

colorschemeをvimrcに追加。

colorscheme molokai

NeoBundleを追加

次にvimプラグインを追加します。プラグインの管理にはNeoBundleを使います。

$ git clone https://github.com/Shougo/neobundle.vim ~/.vim/bundle/neobundle.vim
$ git clone https://github.com/Shougo/vimproc ~/.vim/bundle/vimproc
$ vi /etc/vimrc

vimrcに以下を追加

if has('vim_starting')
   set runtimepath+=~/.vim/bundle/neobundle.vim
   call neobundle#begin(expand('~/.vim/bundle/'))
       NeoBundleFetch 'Shougo/neobundle.vim'
       NeoBundle 'Shougo/vimproc'
       NeoBundle 'VimClojure'
       NeoBundle 'Shougo/vimshell'
       NeoBundle 'Shougo/unite.vim'
       NeoBundle 'Shougo/neocomplcache'
       NeoBundle 'Shougo/neosnippet'
       NeoBundle 'jpalardy/vim-slime'
       NeoBundle 'scrooloose/syntastic'
       NeoBundle 'scrooloose/nerdtree'
       call neobundle#end()
endif
NeoBundleCheck

filetype off
filetype plugin indent on
filetype indent on

vimrcを保存してからvimを再起動。NeoBundleCheckを設定しているので、起動時にインストールしていないプラグインをインストールか聞かれます。

NeoBundleCheckを設定しない場合は、vimコマンドラインで:NeoBundleInstallとすることで指定したプラグインをインストールできます。

NeoBundleコマンド

:NeoBundleInstall プラグインのインストー
:NeoBundleList プラグインのリスト
:NeoBundleClean プラグインを削除
:NeoBundleUpdate プラグインのアップデート

そのほか、キーバインドに関してなどはまたの機会に。

[amazonjs asin=“B00HWLJI3U” locale=“JP” title=“実践Vim 思考のスピードで編集しよう! (アスキー書籍)”]

リモートサーバーのファイルをSublime Textで開く方法

タイトルのままリモートサーバーのファイルをSublime Textで開く方法です。

sftpやsshfsを使ってリモートサーバーとローカルを同期させる方法もあるようですが、

・ファイル同期を待ちたくない ・ローカルにファイルがいっぱいになるのが嫌だ

ということでよりお手軽なrsubを選んでみました。

1.Sublime Text2の側の設定

以下の手順でrsubのパッケージを追加します。

  1. SublimeTextを開く
  2. Command Palettを開く(CMD + Shift + P)
  3. 「Package Control: Install Package」を選択
  4. 「rsub」を選択してインストー

2.リモートサーバー側の設定

リモートサーバーにログインしたら、rsubをインストールします。

$ sudo wget -O /usr/local/bin/rsub https://raw.github.com/aurora/rmate/master/rmate
$ sudo chmod +x /usr/local/bin/rsub

3.ローカルでsshのconfigを設定

ここで一旦、ローカルに戻りsshのconfigを設定します。

$ vi ~/.ssh/config

以下の2行をconfigに追加して保存。

Host example.com
  RemoteForward 52698 localhost:52698

これで上手くいくはず(?)だったのですが、リモートサーバーでrsubしてもエラーがでてしまいました。

$rsub sample.txt
  /usr/local/bin/rsub: connect: 接続を拒否されました
  /usr/local/bin/rsub: line 321: /dev/tcp/localhost/52698: 接続を拒否されました
  Unable to connect to TextMate on localhost:52698

なので、configを以下のように変更します。

Host example.com
  User example_user
  HostName 123.45.67.890
  Port 22
  RemoteForward 52698 localhost:52698

保存してローカルからリモートサーバーにssh接続をします。

$ ssh example.com

リモートサーバーからrsubでファイルを開いてみます。

$ rsub sample.txt

これで無事にSublime Textでファイルを開くことができました。 開いたファイルはSublime Text上で保存すればリモートサーバーでも反映されます。

[amazonjs asin=“4844335677” locale=“JP” title=“Web制作者のためのSublime Textの教科書 今すぐ最高のエディタを使いこなすプロのノウハウ”]

さくらのVPS(CentOS)にnginxリバースプロキシを入れて高速化する方法

さくらのVPSの初期設定から、nginxを入れてリバースプロキシの設定をするまでの手順を(自分用に)まとめました。

今回最も参考になったのは以下の本です。nginx以外の高速化の手法も豊富でおすすめです。

[amazonjs asin=“4844362526” locale=“JP” title=“WordPress 高速化&スマート運用必携ガイド”]

さくらのVPSの初期設定

さくらのVPSを契約したら、まずはコントロールパネルからサーバーを起動します。

起動したらrootユーザーでssh接続します。パスワードはメールで送付されているはずです。

$ ssh root@160.17.60.189

ここでたまにエラーになるのですが、そんな時はコントロールパネルからサーバーを再起動すれば接続できることが多いです。

次に、ユーザーを追加します。ここでは「username」というユーザーを新しく追加することとします。

$ passwd
$ useradd username

passwordコマンドでパスワードを設定します。

$ passwd username

次に追加したユーザーにsudo権限を与えます。

今回は「wheel」グループにsudo権限を持たせ、追加したユーザーを「wheel」に所属させます。

$ usermod -G wheel username
$ visudo

visudoコマンドで設定ファイルが開くので、#(コメントアウト)を消します。

# %wheel ALL=(ALL) ALL

ついでに最低限のファイアーウォールの設定をiptablesでします。

$ iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
$ iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
$ iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
$ iptables -A INPUT -i lo -j ACCEPT 
$ iptables -A INPUT -p icmp -j ACCEPT
$ iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
$ iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
$ iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$ iptables -P INPUT DROP 
$ iptables -P OUTPUT ACCEPT
$ service iptables save

この辺りの最初の設定は、さくらインターネットサーバの初期設定ガイドに載っています。

yumの準備

アップデートをして、remiやepelなどのレポジトリを追加します。

$ yum update

yum updateで「更新と設定されたパッケージがありません。」などと出てこけたら以下のコマンドを実行したらから再度アップデートしてみてください。

$ yum clean all
$ yum check
$ yum update

remiとepelを追加します。失敗したらURLを最新のものに差し替えてみてください。

$ rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
$ rpm -ivh http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm

nginxのインストー

次にnginxをインストールします。

yumでインストールできるnginxのバージョンを確認。

$ yum info nginx

ちょっと古かったのでnginxのレポジトリを追加してから、インストールします。

$ rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
$ yum install -y nginx

インストールできたらnginxを立ち上げてから、サーバー起動時に自動でnginxが立ち上がるように設定します。

$ service nginx start
$ sudo /sbin/chkconfig nginx on

phpのインストー

PHPをインストールしてphp.iniを編集します。

$ yum --enablerepo=remi -y install php php-cli php-devel php-mbstring php-gd php-pear php-xml
$ vi /etc/php.ini

php.iniは、とりあえず以下のように変更します。

expose_php = Off
date.timezone = "Asia/Tokyo"

nginxでPHPを動かす時に使うphp-fpmを入れて設定ファイルwww.confを編集します。

$ yum --enablerepo=remi -y install php-fpm
$ vi /etc/php-fpm.d/www.conf

細かいチューニングは後から行うとして、まずは以下のように設定します。

user = nginx
group = nginx
pm = static

php-fpmを立ち上げ、これもchkconfig onします。

$ service php-fpm start
$ sudo /sbin/chkconfig php-fpm on

mysqlのインストー

MySQLをインストールします。

$ yum --enablerepo=remi -y install mysql.x86_64 mysql-server.x86_64 php-mysql

ここでは、起動してからrootを「samplepassword」に設定します。

$ service mysqld start
$ sudo /sbin/chkconfig mysqld on
$ mysqladmin -u root password 'samplepassword'
$ mysql -u root -p

wordpressというデータベースを作成します。

create database wordpress default character set utf8 collate utf8_general_ci;

次にwordpressというユーザーを作成し、パスワードを「samplepassword」とします。

grant all privileges on wordpress.* to wordpress@localhost identified by 'samplepassword';

リバースプロキシの設定(nginx.confの編集)

リバースプロキシを設定するために、nginx.confとdefault.confを編集します。

設定ファイルはGistを参照してください。

*さくらのVPS:CentOS64、nginx 1.6.3、PHP 5.4.39で動作確認。 *その他の環境での動作は保証しかねます。

/etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf

設定ファイルを編集し、nginxを再起動します。

$ service nginx restart

バックアップデータの移行

WordPressを使用していてサーバー移転する時のメモです。

htmlディレクトリ以下をすべて圧縮し、データベースはdumpしてバックアップを保存。

$ tar zcvf html.tar.gz html
$ mysqldump -u root -p wordpress > dump.sql

転送先のサーバーにsftpコマンドで接続して、dump.sqlとhtml.tar.gzを転送します。

$sftp root@123.45.67.89
  put dump.sql
  put html.tar.gz

転移先のサーバーにssh接続して、html.tar.gzを解凍&dumpファイルをインポートします。

$ tar zxvf html.tar.gz
$ mysql -u root -p wordpress < dump.sql

これで、CentOS+nginx(リバースプロキシ)+ php-fpmの環境構築は完了です(多分)。

あとはサーバーの環境に合わせてチューニングすればよいかと。

[amazonjs asin=“4048702270” locale=“JP” title=“ハイパフォーマンスHTTPサーバ Nginx入門”]

HTMLに埋め込まれた相対パスを絶対パスに変換する

スクレイピングをした時に、imgタグなどで埋め込まれている画像が相対パスで指定されている場合に絶対パスに変換する関数です。

もっとスマートなやり方がありそうですが。。。ほかの人が改善してくれることを期待して公開してみます。

相対パスのパターン

相対パスのパターンは以下の7通りを想定しています。抜けているパターンがあれば教えてください。

絶対パス

http://example.jp/sample.jpg

・http(s)の省略

//example.jp/sample.jpg

ディレクトリ以下を指定

/images/sample.jpg

・同一ディレクトリ内

./sample.jpg

・同一ディレクトリ内

sample.jpg

・親ディレクトリ内

../../sample.jpg

・並列するディレクトリ内

../../images/sample.jpg

相対パスから絶対パスに変換するPHP関数

ベースURLと変換する相対パスを引数に指定します。

ベースURLを元に、相対パス絶対パスに変換します。

/**
 * スクレイピングなどで画像URLを取得する時に使うために 
 * ベースURLを元に相対パスから絶対パスに変換する関数
 * 
 * @param string $target_path 変換する相対パス
 * @param string $base ベースとなるパス
 * @return $uri string 絶対パスに変換済みのパス
 */
function convert_to_uri($target_path, $base) {
  $component = parse_url($base);

  $directory = preg_replace('!/[^/]*$!', '/', $component["path"]);

  switch (true) {

    // [0] 絶対パスのケース(簡易版)
    case preg_match("/^http/", $target_path):
      $uri =  $target_path;
      break;

    // [1]「//exmaple.jp/aa.jpg」のようなケース
    case preg_match("/^\/\/.+/", $target_path):
      $uri =  $component["scheme"].":".$target_path;
      break;

    // [2]「/aaa/aa.jpg」のようなケース
    case preg_match("/^\/[^\/].+/", $target_path):
      $uri =  $component["scheme"]."://".$component["host"].$target_path;
      break;

    // [3]「./aa.jpg」のようなケース
    case preg_match("/^\.\/(.+)/", $target_path,$maches):
      $uri =  $component["scheme"]."://".$component["host"].$directory.$maches[1];
      break;

    // [4]「aa.jpg」のようなケース([3]と同じ)
    case preg_match("/^([^\.\/]+)(.*)/", $target_path,$maches):
      $uri =  $component["scheme"]."://".$component["host"].$directory.$maches[1].$maches[2];
      break;

    // [5]「../aa.jpg」のようなケース
    case preg_match("/^\.\.\/.+/", $target_path):
      //「../」をカウント
      preg_match_all("!\.\./!", $target_path, $matches);
      $nest =  count($matches[0]);

      //ベースURLのディレクトリを分解してカウント
      $dir = preg_replace('!/[^/]*$!', '/', $component["path"])."\n";
      $dir_array = explode("/",$dir);
      array_shift($dir_array);
      array_pop($dir_array);
      $dir_count = count($dir_array);

      $count = $dir_count - $nest;

      $pathto="";
      $i = 0;
      while ( $i < $count) {
        $pathto .= "/".$dir_array[$i];
        $i++;
      }
      $file = str_replace("../","",$target_path);
      $uri =  $component["scheme"]."://".$component["host"].$pathto."/".$file;

      break;
  }

  return $uri;
}

関数の実行結果

上記の関数を相対パス7パターンで実行してみます。

$base = "http://example.jp/posts/2015/06/convert_to_uri.html";
$pathes = array(
  "http://example.jp/sample.jpg",
  "//example.jp/sample.jpg",
  "/images/sample.jpg",
  "./sample.jpg",
  "sample.jpg",
  "../../sample.jpg",
  "../../images/sample.jpg"
);

foreach ($pathes as $key => $path) {
  echo convert_to_uri($path,$base)."\n";
}

実行結果は以下の通りです。なんとか上手くいった気がします。

http://example.jp/sample.jpg
http://example.jp/sample.jpg
http://example.jp/images/sample.jpg
http://example.jp/posts/2015/06/sample.jpg
http://example.jp/posts/2015/06/sample.jpg
http://example.jp/posts/sample.jpg
http://example.jp/posts/images/sample.jpg

フィードバックなどあればコメントなどにお願いします!

[amazonjs asin=“B00BCQ5Q96” locale=“JP” title=“Programming PHP”]

[amazonjs asin=“B00P0UDWQY” locale=“JP” title=“パーフェクトPHP”]