> 백엔드 개발 > PHP 튜토리얼 > HTML 태그를 구문 분석하고, 빠르게 노드를 찾고, 노드 정보를 얻습니다.

HTML 태그를 구문 분석하고, 빠르게 노드를 찾고, 노드 정보를 얻습니다.

WBOY
풀어 주다: 2016-07-25 08:48:49
원래의
1442명이 탐색했습니다.
자세한 소개와 사용법을 보시려면 소스코드를 클릭해주세요.
  1. /**
  2. * htmlmap 파서
  3. *
  4. * @category TagParse
  5. * @package TagParse
  6. * @author this
  7. * @copyright 2014 this * @version 1.0
  8. * @link http://www.blogkun.com
  9. * @ 1.0
  10. 이후*/
  11. 네임스페이스 TagParse;
  12. /**
  13. * TagDomRoot
  14. *
  15. * @category TagParse
  16. * @package TagParse
  17. * @author kun
  18. * @copyright 2014 kun
  19. * @license http://www.php.net/license/3_01.txt PHP 라이센스 3.01
  20. * @version 1.0
  21. * @link http://www.blogkun.com
  22. * @since 1.0
  23. */
  24. class TagDomRoot
  25. {
  26. public $tag = 'root';
  27. public $plaintext;
  28. public $child = array();
  29. public $level = 0;
  30. public static $ TagParseError = false;
  31. protected static $TagSet = array();
  32. protected static $FoundNode = array();
  33. public static $ErrorTag = array();
  34. /**
  35. * initProperty
  36. *
  37. * @access public
  38. *
  39. * @return null
  40. */
  41. 공용 함수 initProperty()
  42. {
  43. $TagParseError = false;
  44. $TagSet = array();
  45. $FoundNode = array();
  46. $DumpScriptCode = array();
  47. $ErrorTag = array();
  48. }
  49. /**
  50. * __construct
  51. *
  52. * @param string $str 구문 분석할 태그 문자열.
  53. *
  54. * @access public
  55. *
  56. * @return TagDomRoot
  57. */
  58. 공개 함수 __construct($str)
  59. {
  60. $ this->_removeNoise($str);
  61. if ($str === null) {
  62. self::$TagParseError = true;
  63. } else {
  64. $l = strpos($str , '<');
  65. if ($l !== false) {
  66. $this->plaintext = substr($str, 0, $l);
  67. }
  68. $res = preg_match_all('~>(.*?)<~s', $str, $matches);
  69. if ($res !== false && $res > 0) {
  70. $this->plaintext .= implode($matches[1]);
  71. }
  72. $r = strrpos($str, '>');
  73. if ($ r !== false) {
  74. $this->plaintext .= substr($str, $r 1);
  75. }
  76. $tagCollect = array();
  77. $attrCollect = array();
  78. $innerContentCollect = array();
  79. if ($this->parseTag($str, $tagCollect, $attrCollect, $innerContentCollect) === false) {
  80. self::$TagParseError = true;
  81. }
  82. foreach ($tagCollect as $index => $tag) {
  83. $this->child[] = new TagDomNode($tag , $this, $attrCollect[$index], $innerContentCollect[$index], $this->level 1);
  84. }
  85. }
  86. }
  87. /**
  88. * parsTag
  89. *
  90. * @param 혼합 $str 설명.
  91. * @param 혼합 &$tagCollect 설명.
  92. * @param 혼합 &$attrCollect 설명.
  93. * @param 혼합 &$innerContentCollect 설명.
  94. *
  95. * @access protected
  96. *
  97. * @return 부울 값.
  98. */
  99. 보호된 함수 parseTag($str, 배열 &$tagCollect, 배열 &$attrCollect, 배열 &$innerContentCollect)
  100. {
  101. $selfClosingTags = array('img' => 1, 'br ' => 1, '입력' => 1, '메타' => 1, '링크' => 1, '시간' => 1, '베이스' => 1, '삽입' => 1, '스페이서' => 1);
  102. $end = -2;
  103. $close = 0;
  104. $error = false;
  105. $tag = '';
  106. while(true) {
  107. $l = strpos($str, '<', $end strlen($tag) 2);
  108. if ($l === false) {//parse end
  109. break;
  110. }
  111. if (strpos(substr($str, $l, 2), '/') !== false) {//잉여 닫는 태그, 버리기
  112. $error = true;
  113. $end = $l strlen( $tag);
  114. self::$ErrorTag[] = substr($str, $l, strpos($str, '>', $l)-$l 1);
  115. 계속;
  116. }
  117. $r = strpos($str, '>', $l);
  118. $tag = substr($str, $l 1, $r-$l-1);
  119. if (!ctype_alpha($tag[0]) || strpos($tag, '<') !== false) {
  120. $end = $r 1;
  121. 계속;
  122. }
  123. $tag = preg_replace("~n ~", ' ', $tag);
  124. $space = strpos($tag, ' ');
  125. if ($space !== false) {
  126. $attrCollect[] = substr($tag, $space 1);
  127. $tag = substr($tag, 0, $space);
  128. } else {
  129. $attrCollect[] = '' ;
  130. }
  131. $tagCollect[] = $tag;
  132. if (isset($selfClosingTags[$tag])) {
  133. $innerContentCollect[] = '';
  134. $end = $ r-strlen($tag)-2;
  135. $close = $r 1;
  136. 계속;
  137. }
  138. $countOpen = -1;
  139. $open = strpos($ str, '<'.$tag, $close);
  140. $close = strpos($str, '', $open);
  141. if ($close === false) {//여분 여는 태그
  142. $innerContentCollect[] = substr($str, $r 1);
  143. $error = true;
  144. self::$ErrorTag[] = '< ;'.$tag.'>';
  145. break;
  146. }
  147. $start = $open;
  148. while ($open < $close && $open !== false) {
  149. $countOpen ;
  150. $open = strpos($str, '<'.$tag, $open strlen($tag));
  151. }
  152. while ($countOpen > 0 && $close !== false) {
  153. $open = strpos($str, '<'.$tag, $close strlen($tag) 3);
  154. $close = strpos($str, '', $close strlen($tag) 3);
  155. if ($close === false) {
  156. break;
  157. }
  158. $countOpen--;
  159. while ($open < $close && $open !== false) {
  160. $open = strpos($str, '<' .$tag, $open strlen($tag) 3);
  161. $countOpen ;
  162. }
  163. }
  164. if ($close === false) {//标签闭합불配对
  165. $innerContentCollect[] = substr($str, $r 1);
  166. $error = true;
  167. break;
  168. }
  169. $end = $close;
  170. $r = strpos($ str, '>', $start);
  171. $innerContentCollect[] = substr($str, $r 1, $end - $r - 1);
  172. }
  173. return !$ error;
  174. }
  175. /**
  176. * _removeNoise
  177. *
  178. * @param string &$str 구문 분석할 태그 문자열.
  179. *
  180. * @access private
  181. *
  182. * @return string
  183. */
  184. 비공개 함수 _removeNoise(&$str)
  185. {
  186. $str = preg_replace('~~is', '', $str);
  187. $str = preg_replace('~~is', ' ', $str);
  188. $str = preg_replace('~~is', '', $str);
  189. }
  190. /**
  191. * parseSelectors
  192. *
  193. * @param string $selectors 사용자 선택 조건
  194. * @param array &$selectorsTag 태그
  195. * @param array &$selectorsAttr 속성
  196. *
  197. * @액세스 보호됨
  198. *
  199. * @return null
  200. */
  201. 보호 함수 parseSelectors($selectors, array &$selectorsTag, array &$selectorsAttr)
  202. {
  203. preg_match_all('~([wd] )([[wd -="._/ ] ])?~', $selectors, $matches);
  204. $selectorsTag = $matches[1];
  205. foreach ($matches[2] as $key => $value) {
  206. $selectorsAttr[$key] = array();
  207. if ($value !== '') {
  208. preg_match_all('~([wd-] )="([wd -. _/] )"~', $value, $matches);
  209. foreach ($matches[1] as $index => $attr) {
  210. $selectorsAttr[$key][$attr] = $matches[2][$index];
  211. }
  212. }
  213. }
  214. }
  215. /**
  216. * find
  217. *
  218. * @param 혼합 $selectors 사용자 선택 조건.
  219. * @param array $selectorsTag 태그.
  220. * @param array $selectorsAttr 속성.
  221. *
  222. * @access public
  223. *
  224. * @return 배열
  225. */
  226. 공개 함수 find($selectors , $selectorsTag = array(), $selectorsAttr = array())
  227. {
  228. if ($selectors !== null) {
  229. $this->parseSelectors($selectors, $selectorsTag, $selectorsAttr );
  230. }
  231. var_dump($selectorsTag, $selectorsAttr);exit();
  232. if (!empty($selectorsTag)) {
  233. $this->seek($selectorsTag, $selectorsAttr );
  234. foreach ($this->child as $key => $node) {
  235. $node->find(null, $selectorsTag, $selectorsAttr);
  236. }
  237. }
  238. if ($selectors !== null) {
  239. $res = self::$FoundNode;
  240. self::$FoundNode = array();
  241. return $res ;
  242. }
  243. }
  244. /**
  245. * findGlobal
  246. *
  247. * @param string $selectors 사용자 선택 조건
  248. *
  249. * @access public
  250. *
  251. * @return 배열
  252. */
  253. 공개 함수 findGlobal($selectors)
  254. {
  255. $space = strpos($selectors, ' ', strpos($selectors, ']' ));
  256. if ($space === false) {
  257. return $this->findOneGlobal($selectors);
  258. } else {
  259. $selectorsAttr = array();
  260. $selectorsTag = array();
  261. $this->findOneGlobal(substr($selectors, 0, $space), false);
  262. $this->parseSelectors(substr($selectors, $space 1) , $selectorsTag, $selectorsAttr);
  263. if (!empty(self::$FoundNode) && !empty($selectorsTag)) {
  264. $nodes = self::$FoundNode;
  265. self::$ FoundNode = array();
  266. foreach ($nodes as $key => $node) {
  267. $node->seek($selectorsTag, $selectorsAttr);
  268. }
  269. }
  270. }
  271. $res = self::$FoundNode;
  272. self::$FoundNode = array();
  273. return $res;
  274. }
  275. /**
  276. * 탐색
  277. *
  278. * @param 배열 $selectorsTag 태그.
  279. * @param 배열 $selectorsAttr 속성.
  280. *
  281. * @access protected
  282. *
  283. * @return null
  284. */
  285. 보호된 함수 탐색($selectorsTag, $selectorsAttr)
  286. {
  287. foreach ($this->child as $key => $node) {
  288. $isFind = true;
  289. if ($node->tag === $selectorsTag[0]) {
  290. foreach ($selectorsAttr[0] as $attrName => $ value) {
  291. if (isset($node->attr[$attrName])
  292. && (preg_match('~.*? '.$value.' .*?~', $node ->attr[$attrName]) > 0
  293. || preg_match('~^'.$value.'$~', $node->attr[$attrName]) > 0
  294. | | preg_match('~^'.$value.' ~', $node->attr[$attrName]) > 0
  295. || preg_match('~ '.$value.'$~', $node ->attr[$attrName]) > 0)
  296. ) {
  297. 계속;
  298. } else {
  299. $isFind = false;
  300. break;
  301. }
  302. }
  303. } else {
  304. $isFind = false;
  305. }
  306. if ($isFind) {
  307. if (count($selectorsTag) === 1) {
  308. self::$ FoundNode[] = $node;
  309. } else {
  310. $node->seek(
  311. array_slice($selectorsTag, 1),
  312. array_slice($selectorsAttr, 1)
  313. );
  314. }
  315. }
  316. }
  317. }
  318. /**
  319. * findOneGlobal
  320. *
  321. * @param string $selector 사용자의 선택 조건.
  322. * @param bool $isReturn 날씨 반환 값.
  323. *
  324. * @access public
  325. *
  326. * @return 배열
  327. */
  328. 공개 함수 findOneGlobal($selector, $isReturn = true)
  329. {
  330. preg_match('~([wd] )([[wd -="._/] ])?~', $selector, $matches);
  331. $tag = $matches[1];
  332. $ attr = array();
  333. if (isset($matches[2])) {
  334. preg_match_all('~([wd-] )="([wd-. _/] )"~', $matches[2], $matches);
  335. foreach ($matches[1] as $key => $value) {
  336. $attr[$value] = $matches [2][$key];
  337. }
  338. }
  339. if (isset(self::$TagSet[$tag])) {
  340. foreach (self::$TagSet[$tag] as $attrValue => $nodeArray) {
  341. $isFind = true;
  342. foreach ($attr as $attrName => $value) {
  343. if (preg_match('~'.$attrName.'= ".*? '.$value.' .*?"~', $attrValue)
  344. || preg_match('~'.$attrName.'="'.$value.' .*?"~', $attrValue)
  345. || preg_match('~'.$attrName.'=".*? '.$value.'"~', $attrValue)
  346. || preg_match('~'.$attrName. '="'.$value.'"~', $attrValue)
  347. ) {
  348. 계속;
  349. } else {
  350. $isFind = false;
  351. break;
  352. }
  353. }
  354. if ($isFind) {
  355. foreach ($nodeArray as $key => $node) {
  356. self::$FoundNode[] = $node;
  357. }
  358. }
  359. }
  360. }
  361. if ($isReturn) {
  362. $res = self ::$FoundNode;
  363. self::$FoundNode = array();
  364. return $res;
  365. }
  366. }
  367. }
  368. /**
  369. * TagDomNode
  370. *
  371. * @uses TagDomRoot
  372. *
  373. * @category TagParse
  374. * @package TagParse
  375. * @author kun
  376. * @copyright 2014군
  377. * @license http://www.php.net/license/3_01.txt PHP 라이센스 3.01
  378. * @version 1.0
  379. * @link http://www. blogkun.com
  380. * @since 1.0
  381. */
  382. class TagDomNode는 TagDomRoot를 확장합니다
  383. {
  384. public $attr = array();
  385. public $parent = null;
  386. /**
  387. * __construct
  388. *
  389. * @param 혼합 $tag 태그.
  390. * @param 혼합 $parent 상위 노드.
  391. * @param 혼합 $attr 속성.
  392. * @param 혼합 $innerContent 태그 콘텐츠.
  393. * @param 혼합 $level 노드 수준.
  394. *
  395. * @access public
  396. *
  397. * @return TagDomNode
  398. */
  399. 공개 함수 __construct($tag, $parent, $attr, $innerContent, $level)
  400. {
  401. $this->tag = $tag;
  402. $this->parent = $parent;
  403. $this->_parseAttr($attr);
  404. $this->level = $level;
  405. $l = strpos($ innerContent, '<');
  406. if ($l !== false) {
  407. $this->plaintext = substr($innerContent, 0, $l);
  408. }
  409. $ res = preg_match_all('~>(.*?)<~s', $innerContent, $matches);
  410. if ($res !== false && $res > 0) {
  411. $this ->plaintext .= implode($matches[1]);
  412. } else {
  413. $this->plaintext .= $innerContent;
  414. }
  415. $r = strrpos($innerContent, '>');
  416. if ($r !== false) {
  417. $this->plaintext .= substr($innerContent, $r 1);
  418. }
  419. $tagCollect = array();
  420. $attrCollect = array();
  421. $innerContentCollect = array();
  422. if ($this->parseTag($innerContent, $tagCollect, $attrCollect , $innerContentCollect) === false) {
  423. self::$TagParseError = true;
  424. }
  425. foreach ($tagCollect as $index => $tag) {
  426. $this->child[] = new TagDomNode($tag, $this, $attrCollect[$index], $innerContentCollect[$index], $this->level 1);
  427. }
  428. if (!isset(self::$TagSet[$this->tag])) {
  429. self::$TagSet[$this->tag] = array();
  430. }
  431. if (!isset(self::$TagSet[$this->tag][$attr])) {
  432. self::$TagSet[$this->tag][$ attr] = array();
  433. }
  434. self::$TagSet[$this->tag][$attr][] = &$this;
  435. }
  436. /* *
  437. * _parseAttr
  438. *
  439. * @param string $str 속성 문자열.
  440. *
  441. * @access public
  442. *
  443. * @return null
  444. */
  445. 비공개 함수 _parseAttr($str)
  446. {
  447. preg_match_all('~(?[w-] )="(?.*?) "~s', $str, $matches);
  448. foreach ($matches['attrName'] as $key => $value) {
  449. $this->attr[$value] = $matches ['attrValue'][$key];
  450. }
  451. }
  452. }
复代码


원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿