<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>-Flyぁ梦- &#187; PHP</title>
	<atom:link href="http://blog.11034.org/category/coding/php/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.11034.org</link>
	<description></description>
	<lastBuildDate>Sun, 22 Jun 2025 08:59:05 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.2.38</generator>
	<item>
		<title>敏感词过滤，PHP实现的Trie树</title>
		<link>http://blog.11034.org/2012-07/trie_in_php.html</link>
		<comments>http://blog.11034.org/2012-07/trie_in_php.html#comments</comments>
		<pubDate>Tue, 03 Jul 2012 14:43:25 +0000</pubDate>
		<dc:creator><![CDATA[-Flyぁ梦-]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Trie]]></category>
		<category><![CDATA[UTF-8]]></category>
		<category><![CDATA[字符串]]></category>
		<category><![CDATA[数据结构]]></category>

		<guid isPermaLink="false">http://blog.stariy.org/?p=1174</guid>
		<description><![CDATA[项目需求，要做敏感词过滤，对于敏感词本身就是一个CRUD的模块很简单，比较麻烦的就是对各种输入的敏感词检测了。 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>项目需求，要做敏感词过滤，对于敏感词本身就是一个CRUD的模块很简单，比较麻烦的就是对各种输入的敏感词检测了。用Trie树来实现是比较通用的一种办法吧，之前一直没机会用过这种数据结构，正好试着写了一下。</p>
<p>因为用PHP实现，关联数组用的很舒服。第一个要解决的是字符集的问题，如果在Java中就比较好办统一的Unicode，在PHP中因为常用UTF-8字符集，默认有1-4个字节不同的长度来表示一个字符，于是写了个Util类来将普通的UTF-8字符串转换成字符数组，每一个元素是一个UTF-8串形成的字符。这一点比较容易实现的，根据UTF-8字符集的格式而来就好。<br />
<span id="more-1174"></span></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
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
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> get_chars<span style="color: #009900;">&#40;</span><span style="color: #000088;">$utf8_str</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$s</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$utf8_str</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$len</span> <span style="color: #339933;">=</span> <span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$s</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$len</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$chars</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$len</span><span style="color: #339933;">;</span><span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$c</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$s</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$n</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ord</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$c</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$n</span> <span style="color: #339933;">&gt;&gt;</span> <span style="color: #cc66cc;">7</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>		<span style="color: #666666; font-style: italic;">//0xxx xxxx, asci, single</span>
			<span style="color: #000088;">$chars</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$c</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$n</span> <span style="color: #339933;">&gt;&gt;</span> <span style="color: #cc66cc;">4</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">15</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> 	<span style="color: #666666; font-style: italic;">//1111 xxxx, first in four char</span>
			<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$len</span> <span style="color: #339933;">-</span> <span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$chars</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$c</span><span style="color: #339933;">.</span><span style="color: #000088;">$s</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #000088;">$s</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #000088;">$s</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">3</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
				<span style="color: #000088;">$i</span> <span style="color: #339933;">+=</span> <span style="color: #cc66cc;">3</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$n</span> <span style="color: #339933;">&gt;&gt;</span> <span style="color: #cc66cc;">5</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">7</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> 	<span style="color: #666666; font-style: italic;">//111x xxxx, first in three char</span>
			<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$len</span> <span style="color: #339933;">-</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$chars</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$c</span><span style="color: #339933;">.</span><span style="color: #000088;">$s</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #000088;">$s</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
				<span style="color: #000088;">$i</span> <span style="color: #339933;">+=</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$n</span> <span style="color: #339933;">&gt;&gt;</span> <span style="color: #cc66cc;">6</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> 	<span style="color: #666666; font-style: italic;">//11xx xxxx, first in two char</span>
			<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$len</span> <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$chars</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$c</span><span style="color: #339933;">.</span><span style="color: #000088;">$s</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
				<span style="color: #000088;">$i</span><span style="color: #339933;">++;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$chars</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>字符单位确认以后，就是写Trie树了。简单的算法，从根路径开始给每个字符建一个关联数组，当字符串结束的时候，用一个null表示结尾。</p>
<p>删除一个串，只要找到串中任意一个字符的子元素数量为1，就表示只有这个串了，整个删除就好了；若子元素数量大于1，则继续根据字符找下去，直到末尾的null。</p>
<p>查找一个串（完全匹配），一直根据字符找到null为止就表明存在，任一字符不存在就表明串不存在。</p>
<p>验证一个长串是否含有任一串，这边算法比较挫，按照每个字符开始都在Trie树种搜索一遍，走的回头路比较多，复杂度有O(n * m)，n为长串长度，m为Trie树深度，不过因为中文Trie树深度很浅，勉强还过得去（英文字符串深度很长）。</p>
<p>然后因为PHP没有全局缓存的机制，每次都要从数据库中读取全部的敏感词，然后建立Trie树再去匹配串的话太麻烦了，采取的办法是将Trie内部的关联数组序列化后直接保存在数据库中，每次只要读取这条数据，然后反序列化，Trie树就回来了。当然进行串的插入和删除，将更新这个序列化数据。</p>
<p>可改进的地方：</p>
<ol>
<li>当某一条路径只有这个串即关联数组数量为1时，可以压缩子树</li>
<li>改进Trie树为AC自动机，即每个节点都添加一个失败指针，指向匹配失败后回到树的哪个节点，这样就仅仅是O(n)的复杂度了。建树的过程比较复杂，对每个插入的串的子串进行处理，运行时查询的效率非常高</li>
</ol>
<p>贴代码：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> TrieTree<span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$tree</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> insert<span style="color: #009900;">&#40;</span><span style="color: #000088;">$utf8_str</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$chars</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span>UTF8Util<span style="color: #339933;">::</span><span style="color: #004000;">get_chars</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$utf8_str</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$chars</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">//串结尾字符</span>
		<span style="color: #000088;">$count</span> <span style="color: #339933;">=</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$chars</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$T</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">tree</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$count</span><span style="color: #339933;">;</span><span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$c</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$chars</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$c</span><span style="color: #339933;">,</span> <span style="color: #000088;">$T</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$T</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$c</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">//插入新字符，关联数组</span>
			<span style="color: #009900;">&#125;</span>
			<span style="color: #000088;">$T</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$T</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$c</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> remove<span style="color: #009900;">&#40;</span><span style="color: #000088;">$utf8_str</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$chars</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span>UTF8Util<span style="color: #339933;">::</span><span style="color: #004000;">get_chars</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$utf8_str</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$chars</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_find<span style="color: #009900;">&#40;</span><span style="color: #000088;">$chars</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>	<span style="color: #666666; font-style: italic;">//先保证此串在树中</span>
			<span style="color: #000088;">$chars</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$count</span> <span style="color: #339933;">=</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$chars</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$T</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">tree</span><span style="color: #339933;">;</span>
			<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$count</span><span style="color: #339933;">;</span><span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$c</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$chars</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
				<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$T</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$c</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>		<span style="color: #666666; font-style: italic;">//表明仅有此串</span>
					<span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$T</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$c</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
					<span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
				<span style="color: #009900;">&#125;</span>
				<span style="color: #000088;">$T</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$T</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$c</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> _find<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$chars</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$count</span> <span style="color: #339933;">=</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$chars</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$T</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">tree</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$count</span><span style="color: #339933;">;</span><span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$c</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$chars</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$c</span><span style="color: #339933;">,</span> <span style="color: #000088;">$T</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
			<span style="color: #000088;">$T</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$T</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$c</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> find<span style="color: #009900;">&#40;</span><span style="color: #000088;">$utf8_str</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$chars</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span>UTF8Util<span style="color: #339933;">::</span><span style="color: #004000;">get_chars</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$utf8_str</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$chars</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_find<span style="color: #009900;">&#40;</span><span style="color: #000088;">$chars</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> contain<span style="color: #009900;">&#40;</span><span style="color: #000088;">$utf8_str</span><span style="color: #339933;">,</span> <span style="color: #000088;">$do_count</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$chars</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span>UTF8Util<span style="color: #339933;">::</span><span style="color: #004000;">get_chars</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$utf8_str</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$chars</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$len</span> <span style="color: #339933;">=</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$chars</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$Tree</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">tree</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$count</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$len</span><span style="color: #339933;">;</span><span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$c</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$chars</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$c</span><span style="color: #339933;">,</span> <span style="color: #000088;">$Tree</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>	<span style="color: #666666; font-style: italic;">//起始字符匹配</span>
				<span style="color: #000088;">$T</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$Tree</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$c</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
				<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$j</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span><span style="color: #000088;">$j</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$len</span><span style="color: #339933;">;</span><span style="color: #000088;">$j</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
					<span style="color: #000088;">$c</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$chars</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$j</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
					<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$T</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
						<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$do_count</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
							<span style="color: #000088;">$count</span><span style="color: #339933;">++;</span>
						<span style="color: #009900;">&#125;</span>
						<span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
							<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
						<span style="color: #009900;">&#125;</span>
					<span style="color: #009900;">&#125;</span>
					<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$c</span><span style="color: #339933;">,</span> <span style="color: #000088;">$T</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
						<span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
					<span style="color: #009900;">&#125;</span>
					<span style="color: #000088;">$T</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$T</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$c</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
				<span style="color: #009900;">&#125;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$do_count</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #000088;">$count</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> contain_all<span style="color: #009900;">&#40;</span><span style="color: #000088;">$str_array</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$str_array</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$str</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">contain</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$str</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> export<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #990000;">serialize</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">tree</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> import<span style="color: #009900;">&#40;</span><span style="color: #000088;">$str</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">tree</span> <span style="color: #339933;">=</span> <span style="color: #990000;">unserialize</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$str</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h4  class="related_post_title">看看 Trie , UTF-8 , 字符串 , 数据结构</h4><ul class="related_post"><li>2013-10-31 -- <a target="_blank" href="http://blog.11034.org/2013-10/hulu.html" title="hulu校招">hulu校招</a></li><li>2012-12-06 -- <a target="_blank" href="http://blog.11034.org/2012-12/string.html" title="整理下字符串的一些数据结构和算法">整理下字符串的一些数据结构和算法</a></li><li>2012-12-06 -- <a target="_blank" href="http://blog.11034.org/2012-12/suffix_array.html" title="一套可用的后缀数组代码">一套可用的后缀数组代码</a></li><li>2012-12-06 -- <a target="_blank" href="http://blog.11034.org/2012-12/ac_automachine.html" title="一个OOP的AC自动机代码">一个OOP的AC自动机代码</a></li><li>2012-03-22 -- <a target="_blank" href="http://blog.11034.org/2012-03/java_util_collections.html" title="java.util中的集合类解析">java.util中的集合类解析</a></li></ul><h4 class="related_post_title">看看 PHP </h4><ul class="related_post"><li>2012-06-28 -- <a target="_blank" href="http://blog.11034.org/2012-06/get_video_cover_image.html" title="各大视频网站的视频截图抓取">各大视频网站的视频截图抓取</a></li>]]></content:encoded>
			<wfw:commentRss>http://blog.11034.org/2012-07/trie_in_php.html/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>各大视频网站的视频截图抓取</title>
		<link>http://blog.11034.org/2012-06/get_video_cover_image.html</link>
		<comments>http://blog.11034.org/2012-06/get_video_cover_image.html#comments</comments>
		<pubDate>Thu, 28 Jun 2012 15:09:08 +0000</pubDate>
		<dc:creator><![CDATA[-Flyぁ梦-]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[截图]]></category>
		<category><![CDATA[正则]]></category>
		<category><![CDATA[视频]]></category>

		<guid isPermaLink="false">http://blog.stariy.org/?p=1167</guid>
		<description><![CDATA[新的一个项目，要有视频的功能，当然只是简单的贴URL和标题罢了，不会涉及到要去上传视频文件，但是在展示视频的时 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>新的一个项目，要有视频的功能，当然只是简单的贴URL和标题罢了，不会涉及到要去上传视频文件，但是在展示视频的时候就需要用到视频截图了，自己去生成截图难度太大了也不现实，去视频的源网站抓取是可行也比较方便的方法。</p>
<p>试过优酷、土豆、酷6、56、腾讯、新浪、搜狐这些国内最大的视频门户，基本都成功获取到截图，其中属优酷最麻烦。</p>
<p><span id="more-1167"></span></p>
<h3>优酷</h3>
<p>感觉优酷不愧为国内第一视频门户吧，技术算是最成熟的，安全也做得最好，直接体现在获取它的视频截图真心不容易。用查看html源码的方式根本无法实现，用firebug等工具找图片也不行因为图片是在flash里的。不过网上已经有文章告诉了方法，自己也可以通过httpfox或chrome自带的Network工具查看发起的http请求去找图片地址，优酷通过向URL：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #0000ff;">'http://v.youku.com/player/getPlayList/VideoIDS/视频的ID/version/5/source/out'</span></pre></td></tr></table></div>

<p>而视频的ID就是普通视频URL中id_xxx中的xxx串，URL返回一段json字符串，其中的logo字段就是图片地址，可以发现此图片地址也是一个动态请求，非常复杂。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'http://v.youku.com/v_show/id_XMTA0NTM2MzI4.html'</span><span style="color: #339933;">;</span>
<span style="color: #990000;">preg_match_all</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/id\_(\w+)[\=|.html]/&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$url</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$u</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'http://v.youku.com/player/getPlayList/VideoIDS/'</span><span style="color: #339933;">.</span><span style="color: #000088;">$id</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/version/5/source/out'</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$json_str</span> <span style="color: #339933;">=</span> <span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$u</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$json</span> <span style="color: #339933;">=</span> <span style="color: #990000;">json_decode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$json_str</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$image_url</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$json</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>data<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>logo<span style="color: #339933;">;</span>
	<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$image_url</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h3>56</h3>
<p>类似优酷，请求url为http://vxml.56.com/json/视频ID/?src=out，视频ID也好辨别。//测试可行，此来源网络</p>
<h3>土豆、酷6、腾讯、新浪、搜狐</h3>
<p>这些都比较简单，打开html源码细心点就能找到image的url，用正则就可以抓取出来了。其中酷6比较麻烦，把url中的:和.都用unicode编码了，先用字符串匹配给转了回来再去正则，因为不知道正则字符串中怎么搞反斜杠=.=（\\不起作用咩&#8230;）</p>
<ul>
<li>土豆：开头的js代码中有个属性listData，里面放了5部视频的信息，选第一部，其中的pic属性，正则字符串：/,pic:\&#8221;([\w\/\.\:]+)\&#8221;/</li>
<li>酷6：Ctrl-F搜索bigpicpath属性，也在js代码中，正则字符串：/\&#8221;bigpicpath\&#8221;\:\&#8221;([\w\/\.\:]+)\&#8221;/</li>
<li>腾讯：pic属性，正则字符串：/pic \:\&#8221;([\w\/\.\:]+)\&#8221;/</li>
<li>新浪：pic属性，正则字符串：/pic\: \'([\w\/\.\:]+)\&#8217;/ 和楼上非常相似，难道又是抄袭？哈哈哈</li>
<li>搜狐：cover属性，正则字符串：/var cover=\&#8221;([\w\/\.\:]+)\&#8221;/</li>
</ul>
<p>在网上找资料的时候发现一个看似很好用的PHP的VideoUrlParser类，试了下只有优酷和56是起作用的，然后自己再用正则的办法把剩下的视频网站搞定。</p>
<p><a title="VideoUrlParser.class.origin" href="/wp-content/files/posts/2012-6-video-image-parser/VideoUrlParser.class.origin.php.text" target="_blank">原先的VideoUrlParser类</a></p>
<p><a title="VideoUrlParser.class" href="/wp-content/files/posts/2012-6-video-image-parser/VideoUrlParser.class.php.text" target="_blank">改良后VideoUrlParser类</a></p>
<h4  class="related_post_title">看看 截图 , 正则 , 视频</h4><ul class="related_post"><li>2012-05-15 -- <a target="_blank" href="http://blog.11034.org/2012-05/router_in_play_framework.html" title="Play框架的Router机制和jregex包">Play框架的Router机制和jregex包</a></li></ul><h4 class="related_post_title">看看 PHP </h4><ul class="related_post"><li>2012-07-03 -- <a target="_blank" href="http://blog.11034.org/2012-07/trie_in_php.html" title="敏感词过滤，PHP实现的Trie树">敏感词过滤，PHP实现的Trie树</a></li>]]></content:encoded>
			<wfw:commentRss>http://blog.11034.org/2012-06/get_video_cover_image.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
