教程:任意网页输出为RSS

发现写满了注释就没啥好说的了,姑且称为教程吧。

需要自己操作的核心只是$regex_item和$regex_item2这两个正则的修改。如有兴趣,可另开教程。

聪明的你可能会发现这两个匹配的内容不是一样的吗,那为什么不合二为一呢?

自己体会。

例一:微博热搜

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
<?php
include"gethtml.php";
$title_find[0]=$link_find[0]=$des_find[0]='#/[\x00-\x08\x0b-\x0c\x0e-\x1f]/s#';
$title_replace[0]=$link_replace[0]=$des_replace[0]='';
$footer='</channel></rss>';
//以上为一些初始工作,不用管。
$header='<?xmlversion="1.0"encoding="utf-8"?><rssversion="2.0"><channel><title>热搜</title>';//修改RSS名称
$html=gethtml('https://s.weibo.com/top/summary');//要操作的网页。
$html=strpos($html,'charset=gb')===false?$html:iconv('GB2312','UTF-8//IGNORE',$html);//古董网页专用:(
$regex_item='#<td>.+?td>#s';//正则规则在井号中间,s代表可匹配多行,否则只匹配单行,具体要看网页源代码。
$regex_item2='#.*?<a href="(?<link>.+?)">(?<title>.+?)</a>.*#s';
if(preg_match_all($regex_item,$html,$items)){//在已经抓下来的网页中匹配"代码块",每一"块"的原则是结构高度统一且必须包含链接、标题。概要可无,因为可以用标题替代。
//print_r($items[0]);//调试用,如需调试,把最前面的双斜杠去掉。
foreach($items[0]as$item){
if(preg_match($regex_item2,$item)){
$rss.=preg_replace_callback(
$regex_item2,//对"块"分组捕获链接、标题、摘要并命名。
function($matches){
global$title_find,$title_replace,$link_find,$link_replace,$des_find,$des_replace;
//以下可对title进行替换操作,酌情增减。
$title_find[1]='#的#';
$title_replace[1]='の';
$title_find[2]='#百度#';
$title_replace[2]='一个无耻的网站';
//以下对link进行替换操作,酌情增减。此例增加网站域名,否则链接无效。
$link_find[1]='#(.+)#';
$link_replace[1]='https://s.weibo.com$1';
//以下可对description进行替换操作,酌情增减。此例并无任何操作。
$title=preg_replace($title_find,$title_replace,$matches['title']);//根据上面规则替换后输出title。$matches['title']为上面分组捕获的内容。
$link=preg_replace($link_find,$link_replace,$matches['link']);//根据上面规则替换后输出link。
$des=preg_replace($des_find,$des_replace,$matches['title']);//根据上面规则替换后输出description。
//以下就是一条最基本的RSS内容了。\n和\t只是格式化了代码,并无大用,方便查错。
return"<item>\n\t<title><![CDATA[".$title."]]></title>\n\t<link><![CDATA[".$link."]]></link>\n\t<description><![CDATA[".$des."]]></description>\n</item>\n";
},
$item
);
}
}
//echo  $rss;//调试用
//大功告成,输出收工。
file_put_contents('weibotop.xml',$header.$rss.$footer);
}
?>

图一,此为表达式$regex_item匹配内容,即所谓结构统一且必包含所需元素。

例二:百度知道9图轮播

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
<?php
include"gethtml.php";
$title_find[0]=$link_find[0]=$des_find[0]='#/[\x00-\x08\x0b-\x0c\x0e-\x1f]/s#';
$title_replace[0]=$link_replace[0]=$des_replace[0]='';
$footer='</channel></rss>';
//以上为一些初始工作,不用管。
$header='<?xmlversion="1.0"encoding="utf-8"?><rssversion="2.0"><channel><title>百度知道</title>';//修改RSS名称
$html=gethtml('https://zhidao.baidu.com/');//要操作的网页。
$html=strpos($html,'charset=gb')===false?$html:iconv('GB2312','UTF-8//IGNORE',$html);//古董网页专用:(
$regex_item='#<a href="(.+?)".*?a>#s';//正则规则在井号中间,s代表可匹配多行,否则只匹配单行,具体要看网页源代码。
$regex_item2='#<a href="(?<link>.+?)".+?class="title">(?<title>.+?)</div>.+?class="intro">(?<des>.+?)<.*#s';
if(preg_match_all($regex_item,$html,$items)){//在已经抓下来的网页中匹配"代码块",每一"块"的原则是结构高度统一且必须包含链接、标题。概要可无,因为可以用标题替代。
//print_r($items[0]);//调试用。如需调试,把最前面的双斜杠去掉。
foreach($items[0]as$item){
if(preg_match($regex_item2,$item)){
$rss.=preg_replace_callback(
$regex_item2,//对"块"分组捕获链接、标题、摘要并命名。
function($matches){
global$title_find,$title_replace,$link_find,$link_replace,$des_find,$des_replace;
//以下可对title进行替换操作,酌情增减。
$title_find[1]='#的#';
$title_replace[1]='の';
$title_find[2]='#百度#';
$title_replace[2]='一个无耻的网站';
//以下对link进行替换操作,酌情增减。此例无任何操作。
//以下可对description进行替换操作,酌情增减。此例并无任何操作。
$title=preg_replace($title_find,$title_replace,$matches['title']);//根据上面规则替换后输出title。$matches['title']为上面分组捕获的内容。
$link=preg_replace($link_find,$link_replace,$matches['link']);//根据上面规则替换后输出link。
$des=preg_replace($des_find,$des_replace,$matches['des']);//根据上面规则替换后输出description。
//以下就是一条最基本的RSS内容了。\n和\t只是格式化了代码,并无大用,方便查错。
return"<item>\n\t<title><![CDATA[".$title."]]></title>\n\t<link><![CDATA[".$link."]]></link>\n\t<description><![CDATA[".$des."]]></description>\n</item>\n";
},
$item
);
}
}
//echo $rss;//调试用
//大功告成,输出收工。
file_put_contents('zhidao.xml',$header.$rss.$footer);
}
?>

两个例子应该够用了,举一反三吧。

代码下载:http://feedx.net/rss/tutorial/tutorial200316.tgz

18条评论

  1. 对于小白来说,希望能有详细的视频教程,谢谢了

  2. 感谢!不过我不太习惯这种写在一起的正则,头大了,而且我试了写了下,有点麻烦,容易出奇怪的问题,比如你这个微博热搜的就出问题了(我没有修改代码),你可以自己测试下。我运行的结果http://209.250.231.104/rss/weibotop.xml 。

    其实我觉得分开写比较好吧,我比较习惯分开,直接抓网页源代码暴力匹配,因为再怎么复杂也有规律,比如微博热搜
    标题:td-02\”>\n.*(.*)
    小括号内的为匹配内容
    我测试是51条结果(没有遗漏),标题和链接一一对应,再用正则替换就完美了,只是我不会写代码

  3. 我写的正则匹配:http://209.250.231.104/rss/1.png 直接贴文字有问题

    1. 程序稍微改改就正常了,少了一步判断。
      但程序流程应该就是这样了。

      1. OK!已经搞定了!感谢

  4. 我还没试,但是做好了xml,用什么订阅呢?feedx还是rsshub投稿?我没自建哈。
    PS,怎么网站不能登陆了,没看到登陆选项

    1. 登录要看缘分,哈哈

  5. 谢谢站长,已收录本文到我频道。

  6. 可以帮忙做这个网站的军事栏目吗站长http://www.ifeng.com/

  7. 这两个例子没有看到输出全文,希望能有一个复杂一点的案例,谢谢

    1. 不用仔细找,本站内容本来就不多,全文的教程也有。

  8. RSS遗老遗少,感谢站长的无私奉献。
    站长有没有抓取「观察者」网的计划?谢谢

  9. 站长你好,请问这个需要怎么部署?本人小白,不是太懂

    1. 还是需要基本的PHP环境的,倒也不贵,原来godaddy上域名+主机空间一年只需要$10,不知道现在还有没有。

  10. 真的辛苦了。原来都是用fivefilters,感觉你的技术更好。
    不知道,知乎这类的能不能做?或者股票公告信息更新之类的,类似雪球上面个订阅一个更新。这种做起来其实面更广一点。对于大家的网站都好。

  11. 太难了,我连怎么部署都不会

  12. 不知道有没有参考消息和经济观察报的,我很喜欢这两张报

发表回复取消回复

您的电子邮箱地址不会被公开。必填项已用*标注