php发展

首页 » 常识 » 常识 » PHP多进程抓取网页
TUhjnbcbe - 2022/5/19 20:14:00
北京治湿疹好的医院 https://m-mip.39.net/czk/mipso_8814675.html

我们知道,从父进程到子经常的数据传递相对比较容易一些,但是从子进程传递到父进程就比较的困难。

有很多办法实现进程交互,在php中比较方便的是管道通信。当然,还可以通过socket_pair进行通信。

首先是服务器为了应对每一个请求要做的事情(发送一个url序列,url序列用t分割。而结束标记是n)

functionclientHandle(msgsock,obj)

{

nbuf=;

socket_set_block(msgsock);

do{

if(false===(buf=

socket_read(msgsock,,PHP_NORMAL_READ))){

obj-error(socket_read()failed:reason:.socket_strerror(socket_last_error(msgsock)));

break;

}

nbuf.=buf;

if(substr(nbuf,-1)!=\n){

continue;

}

nbuf=trim(nbuf);

if(nbuf==quit){

break;

}

if(nbuf==shutdown){

break;

}

url=explode(\t,nbuf);

nbuf=;

talkback=serialize(read_ntitle(url));

socket_write(msgsock,talkback,strlen(talkback));

debug(writetotheclient\n);

break;

}while(true);

}

面代码比较关键的一个部分是read_ntitle,这个函数实现多线程的读取标题。

代码如下:(为每一个urlfork一个线程,然后打开管道,读取到的标题写入到管道里面去,主线程一直的在读取管道数据,直到所有的数据读取完毕,最后删除管道)

functionread_ntitle(arr)

{

pipe=newPipe(multi-read);

foreach(arrask=item)

{

pids[k]=pcntl_fork();

if(!pids[k])

{

pipe-open_write();

pid=posix_getpid();

content=base64_encode(read_title(item));

pipe-write(k,content\n);

pipe-close_write();

debug(k:writesuccess!\n);

exit;

}

}

debug(readbegin!\n);

data=pipe-read_all();

debug(readend!\n);

pipe-rm_pipe();

returnparse_data(data);

}

parse_data代码如下,非常的简单,就不说了。

parse_data代码如下,非常的简单,就不说了。

functionparse_data(data)

{

data=explode(\n,data);

new=array();

foreach(dataasvalue)

{

value=explode(,,value);

if(count(value)==2){

value[1]=base64_decode(value[1]);

new[intval(value[0])]=value[1];

}

}

ksort(new,SORT_NUMERIC);

returnnew;

}

上面代码中,还有一个函数read_title比较有技巧。为了兼容性,我没有采用curl,而是直接采用socket通信。

在下载到title标签后,就停止读取内容,以节省时间。代码如下:

functionread_title(url)

{

url_info=parse_url(url);

if(!isset(url_info[host])

!isset(url_info[scheme])){

returnfalse;

}

host=url_info[host];

port=isset(url_info[port])?url_info[port]:null;

path=isset(url_info[path])?url_info[path]:/;

if(isset(url_info[query]))path.=?.url_info[query];

if(empty(port)){

port=80;

}

if(url_info[scheme]==

1
查看完整版本: PHP多进程抓取网页