豆包ko 发表于 2017-3-3 11:22:54

php正则

  先说点题外话。自从给电脑安装了Opera 10.0.1750.0 任务栏就开始莫名其妙的时不时就完全卡死,任务管理器也打不开。因为总是在Opera开启一段时间后出现死机的状况,还以为是Opera有内存泄漏。直到今天早上发现开GaussianView也卡死了,才猜想是中了蠕虫一类病毒。虽然,用Chrome仍然不会卡死(那好吧,在Opera给我留下这样的第一印象的情况下,我只好让它失去不久前才给它分配的“默认浏览器”的权利了)。
  全盘杀毒
  出现了一堆病毒。难道是Opera的安装程序带毒?但是用Rising单杀Opera的相关文件夹,没有发现病毒。(我是很喜欢Opera的,最钟爱的就是它的鼠标手势。当然,Chrome及时响应的界面风格(响应鼠标移动,任何动作都会引起界面的变化,而且,鼠标拿开后,效果是渐渐消失的。可以把它定义成“瞬入淡出”效果吧,与“淡入淡出”让人感觉系统变慢完全是两种不同的感觉)是最吸引我的(用惯了Chrome,刚改用Opera,老是把鼠标放在文本上,然后就无限纳闷地看着指针——为什么还没变成工字型?还有就是Opera的上下文菜单项没有相应按键。对于我这种经常在桌面上点击右键紧接着按R的习惯来说,简直就是一大恶梦——右键了居然还要用鼠标选菜单项,这样长久下去,左手不就萎缩了……
  杀毒完了,发现有uizvr.sys文件在C:\WINDOWS\System32\下,提示删除失败。而网上又搜索不到。真不知道是什么,各位读者若有知道的,不妨告诉我一下。在下非常感谢!
  发现杀了好几个Rootkit病毒,但是网上没有相关的症状说明,所以我还是不确信是不是这个病毒导致了Opera变慢。总之,杀毒完了再打开Opera,内存占用从先前的100~400MB减小到了50~200MB,感觉还行,那就恢复Opera的试用期吧,要是你再敢……
  废话少说,看看php的正则表达式吧。
  这是获取目标网页上所有链接地址的php代码:

<?php
$url="http://www.163.com";
$html=file_get_contents($url,"r");
preg_match_all ("/(<a)([^>]*)(href=)([^>]*)(>)([^<]*)(<)([^>]*)(>)/", $html, $matches);
for ($i=0;$i<count($matches);$i++)
{
echo "|||".$matches[$i]."||".$matches[$i].$matches[$i]."||".$matches[$i]."||".$matches[$i]."<br>";
}
?>
  看看里面的/(<a)([^>]*)(href=)([^>]*)(>)([^<]*)(<)([^>]*)(>)/吧。
  我们知道,链接的形式是这样的:
  <a href="location">text</a>当然,这是最简单的文本链接。
  复杂一点的,比如链接里包含图片的,有style信息的,无非是这样的结构:
  <a*****href="location"*****>****</a>
  正则表达式就该这样写了:(每个部分用小括号括起来)
  1.起始是亘古不变的<a
  2.接下来是不包括">"在内的任意字符,当然不会有"<"出现。[^>]代表任意一个不是">"的字符,.代表任意字符,*表示重复前面的字符0~任意有限次。
  我们知道,<a后面跟任意个非">"字符后,必定遇到href=来定义它的链接地址。要是用这样的正则:
  /(<a) (.*)(>)(href=)/
  会出现什么情况呢?
  这时,preg_match()会往后搜索,直到行尾前的最后一个">",中间所有的">"都被忽略了。这时,再搜索href=就跑到第二个链接里去了,所以不能用,这一个:
  /(<a)([^>]*)(href=) /
  [^>]*限制重复的内容不能是">"所以,遇到">"就不会往下搜索下去,从而停留在第一次匹配(href=)的地方。这样看来,
  /(<a)(.*)(href=)/也是不可行的,试试看:

<?php
$url="http://www.163.com";
$html=file_get_contents($url,"r");
preg_match_all ("/(<a)(.*)(href=)([^>]*)(>)([^<]*)(<)([^>]*)(>)/", $html, $matches);
for ($i=0;$i<count($matches);$i++)
{
echo "|||".$matches[$i]."||".$matches[$i].$matches[$i]."||".$matches[$i]."||".$matches[$i]."<br>";
}
?>
  刷新页面,Chrome审查元素,发现有这样的文本:
  ||| href="http://reg.163.com/reg0.shtml">注册通行证</a> |<a || 这表明分段失败了:
  因为要求输出的第2、3、4、6、8个括号里都没有写明要输出<或>,同时,|||和||中间的内容属于第二个括号(.*)的。
  后面的第三个括号:
  3.固定的href=
  4.把第一个 ">"之前的内容放在这里[^>]*
  5.第一个>
  6.把接下来第一个"<"之前的内容放在这里[^<]*
  7.<
  8.">"之前的内容[^>]*
  9.>
  这样的话,一个基本可用的正则表达式就诞生了。
  其实,可以把最后一个括号改成(/a>) 这样的话, 就能保证每次搜索结束时,总是到达链接的结尾处。用原来的(>)在遇到这样的状况时:
  <a href="location"><img src="image"></a>
  会在img src="image"后面停止,第8段成为 img src="image"而非/a
  好了,正则表达式的用法已经基本会了,接下来就该编出我想要的效果了。首先要弄清楚ikariam页面的结构。
  Chrome把世界地图的index.php下载到本机,经一番研究,发现有这样的数据(太多了,节选):

var map = new Map(44, 33);
map.handleMapData('{"request":{"x_min":30,"x_max"://……
  真是天助我也。这个肯定就是worldmap的数据了。
  仔细研究一下:
  先在map上找一个岛,点上去,出现它的名字Lootios,在haddleMapData里查找,有这样的一段:

"45":{"46":["70","Lootios","1","3","7","7","6","16"],
  回头一看,该岛的坐标正好是。后面的数据又是什么意思呢?先看到岛上有16个城,估计……
  找到它旁边的Shaymios,有11城,查找到相应的数据:

"47":["74","Shaymios","3","4","7","10","7","11"],
  好样的。把我要用的数据粘在这里,就不解释了:

"46":["73","Depuios","4","1","7","4","6","16"],

"44":{"45":["72","Zhexios","3","7","7","3","6","10"],

"43":["163","Chadoios","1","3","14","8","7","16"],

"45":["71","Phiyios","2","5","7","4","8","16"],
  同样的方法发现:
  (1)倒数第二个数字表示木头矿等级。
  (2)名字后面的第一个数字是资源种类(1-Wine,2-Marble,3-Crystal,4-Sulfur)。
  (3)名字后面的第二个数字是奇迹种类(1-
Hephaistos` Forge,2-
Hades` Holy Grove,3-
Demeter`s gardens,    4-
Temple of Athene,5-
Temple of Hermes,6-
Ares` Stronghold,7-
Temple of Poseidon,8-
Colossus)。
  暂时就知道这些。更多的嘛,也有很重要的,但毕竟有替代方法,先放着不管了。
  (今天早上登陆javaeye,发现和昨天一样也是登不进去,看来javaeye可能是每天早上例行维护了吧。这个也不关我事。
  倒是今天下午我终于弄明白任务栏是为什么要卡死了。
  因为每次卡死之后,除了任务栏之外,别的地方都工作正常,所以我把任务管理器置前,Opera打开,关掉屏幕。等吃完饭,打开屏幕,任务栏果然又卡死了。屏幕上提示svchost出错。于是,用任务管理器结束掉占内存最大的svchost,任务栏又活了。原来不是Opera的错,是svchost中毒了。那好吧,杀毒杀不掉,我以后就开着任务管理器工作,一旦看到svchost冒到顶上,就杀掉。)
  如上文,只要能在我的服务器端拿到这个数组,就能解决所有问题了。但是,它是javascript,不知道能不能用fopen()读到。
  好,这个script是写在发送给我的HTML文档里的,那我先试试能不能抓取script。用QQ空间最好了,因为它上面满是javascript。
  在QQ空间的文档里搜索script,终于在最后发现了一段内嵌的script。就用它了。
  首先,需要解决登录的问题,感觉无从下手。当然,从QQ面板上访问时,会给一个跳转地址,先试试它:
  …………
  真傻,明明就是跳转地址,拿来有何用。
  试试http://user.qzone.qq.com/【号码 】吧
  ……怎么还是跳转了……不管了,先试试能不能取得数据:

<?php
$url="http://user.qzone.qq.com/419560202";
$html=file_get_contents($url,"r");
preg_match_all ("/(<a)(.*)(href=)([^>]*)(>)([^<]*)(<)([^>]*)(>)/", $html, $matches);
for ($i=0;$i<count($matches);$i++)
{
echo "|||".$matches[$i]."||".$matches[$i].$matches[$i]."||".$matches[$i]."||".$matches[$i]."<br>";
}
?>
  页面一片空白。
  换个网站吧,ikariam是没有跳转的,跳转问题以后再说。
  啊哈!竟然在javaeye的首页上发现了内嵌的javascript,那就对不起了!
  写正则。
  <script type="text/javascript">……</script>
  1:(<script)
  2:([^>]*)      //可以判断 script的种类
  3:(>)
  4:([^<]*)      //script内容
  5:(</script>)  //当然,/得用转义字符\/
  正则就是:/(<script)([^>]*)(>)([^<]*)(<\/script>)/

<?php
$url="http://www.iteye.com";
$html=file_get_contents($url,"r");
preg_match_all ("/(<script)([^>]*)(>)([^<]*)(<\/script>)/", $html, $matches);
for ($i=0;$i<count($matches);$i++)
{
echo "|||".$matches[$i]."||".$matches[$i]."<br>";
}
?>
  OK,刷新,页面显示:
  ||| type="text/javascript"|| var marqueeing = true; function marquee(){ if(marqueeing) { var container=document.getElementById("advert_a9").getElementsByTagName("ul") container.appendChild(container.firstChild); } } setInterval("marquee()", 2000);
  这不?就拿到了页面内嵌的js代码。
  如果不是内嵌的呢?试一个,Chemspider网页里有这么一句:
  <script type="text/javascript" language="javascript" src="/script.js"></script>
  那我试试这个网址:
  http://www.chemspider.com/script.js
  ……悲剧啊:failed to open stream: HTTP request failed!
  看来,获取在另外的文件中的js,还得想个别的方法。试试fsockopen():
  unable to connect to http://www.chemspider.com/script.js:80 (Unable to find the socket transport "http"
  它还说:
  did you forget to enable it when you configured PHP?
  (看来,我可以用我的本机测试了。)
  接下来,就该研究怎么样从服务器登陆QQ空间了,只有这样,我才能登陆ikariam,从而获得它的数据。
  3天,终于又告一段落了。
页: [1]
查看完整版本: php正则