教程:RSS全文输出,自己动手做。(一)
这里以PHP版为例,尽量说得通俗点吧,水平实在有限,见谅。虽然并没有多高深,但请转载者注意起码的礼貌。
目前我这里所有的获取全文输出的网站大概是三种情况:
- 要输出的内容集中在一页上,也就是看似列表页的页面里集中了你想要的所有内容,并不需要点击“更多”或“继续阅读”才能看到文章整体。比如糗事百科、wiki。
- 有列表页,要查看相应文章必须点击链接进入。
- json方式写入。特征就是查看源文件并不能找到你在浏览器中看到的内容。比如腾讯新闻图片(链接),它的真正内容在这(链接)。
第一种最省事,第二种最常见,第三种稍麻烦。
今天先讲第二种。
以知乎日报为例 (链接),先看代码:(把下列源码存为zhihu.php)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?php include"gethtml.php"; $regex_link='/(?<=<a href="\/story\/).+?(?=")/'; $regex_tit='/(?<=<title>)(.+?)(?= -)/s'; $regex_con='/<span>.*?(?=<div>)/s'; $header='<?xmlversion="1.0"encoding="utf-8"?><rssversion="2.0"><channel><title>知乎日报</title>'; $footer = '</channel></rss>'; $html = gethtml('http://daily.zhihu.com/'); if(preg_match_all($regex_link,$html,$links)){ foreach($links[0]as$link){ $link=preg_replace('/(.+)/','http://daily.zhihu.com/story/$1',$link); $content=gethtml($link); preg_match($regex_con,$content,$article); preg_match($regex_tit,$content,$title); $rss.='<item><title>'.$title[0].'</title><link><![CDATA['.$link.']]></link><description><![CDATA['.$article[0].']]></description></item>'; } file_put_contents('zhihu.xml',$header.$rss.$footer); } ?> |
重点是第8行往后。只解释我认为重要的,不明白的可以讨论。
第2行,引入gethtml方法,来自下面的代码。
看一下第8行gethtml(‘http://daily.zhihu.com/’)得到了什么(链接),虽然有点乱,但是目的达到了,http://daily.zhihu.com/ 我已经抓到本地服务器上。
第9行是要挑出需要的链接 $links(链接)
第13行利用这些链接继续抓取页面 $content=gethtml($link)
第14、15行从$content里查找需要的$title(文章标题)和$article(文章内容)
后面就是按RSS要求的格式输出,并最终生成xml文件。
最后,想办法打开https://feedx.net/rss/tutorial/zhihuu.php,只要程序不出错,就会同目录生成zhihu.xml,订阅地址即为https://feedx.net/rss/tutorial/zhihu.xml
怎么自动打开那个网址呢,crontab、计划任务、cPanel、wordpress插件都可以,如果都没有的话,网上也是有人提供这个服务的,http://cron-job.org,自己去看吧…
上面我说的查找、挑出都是用正则来实现的,此外最好对html特别熟悉,操作起来才能得心应手。
想要自己完成还是要有一定基础的,完全靠伸手是不现实的,还不如去买那些能可视化操作的产品。如果正则不熟或不想学,可以试试PHP Simple HTML DOM Parser,类似jQuery。
============================================
参数的用法:
默认可以不加参数,基本写法是这样的:
1 2 3 4 | $headers=['User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36','Cookie: BAIDUID=4C2D58EAE60F2ACDB32DCAAAA9795A4D:FG=1;H_WISE_SIDS=106370_122302; BDSVRTM=13']; $args=['headers'=>$headers,'header'=>1]; $url='http://feedx.net'; $html=gethtml($url,$args); |
上面的意思是我去抓取的时候让自己更像个浏览器,模拟的是chrome 65.0.3325.162版,还加上了cookie;因为一个网址可能会跳转很多次才到目标网址,通常我们是不用去管这些的,比如我好奇心很重,就可以把header信息也打印出来。还有更多的一些用法可以参考curl自己添加。
============================================
下面是在别人的基础上自己总结的利用curl抓取页面的方法,把下面源码存为gethtml.php,与zhihu.php放于同一目录下。我所有的抓取都是用的这个方法,当然,省事的话可以用 file_get_contents,那就是真正的20行代码完成全文RSS输出了,不过可选的参数就没有了,有的页面会抓取不到。
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 | <?php functiongethtml($url,$args=null){ $proxy=$args["proxy"]?$args["proxy"]:''; $headers=$args["headers"]?$args["headers"]:['User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36']; $nobody=$args["nobody"]?$args["nobody"]:0; $header=$args["header"]?$args["header"]:0; $ch=curl_init(); $options=array( CURLOPT_URL=>@$url, CURLOPT_PROXY =>@$proxy, CURLOPT_HTTPHEADER=>@$headers, CURLOPT_NOSIGNAL=>1, CURLOPT_HEADER=>@$header, CURLOPT_NOBODY=>@$nobody, CURLOPT_RETURNTRANSFER=>1, CURLOPT_FOLLOWLOCATION=>1 ); if(preg_match('/^https/',$url)){ $options[CURLOPT_SSL_VERIFYHOST]=2; $options[CURLOPT_SSL_VERIFYPEER]=0; } curl_setopt_array($ch,$options); $data=curl_exec($ch); $curl_errno=curl_errno($ch); curl_close($ch); if($curl_errno>0){ return'error'; }else{ return$data; } } ?> |
62条评论
太好了,先謝謝了。慢慢看完再請教你。
大概看完了,再次謝謝站長的分享。
簡單來說就是對多層頁面使用函數gethtml獲得主網頁及下級網頁內容後,使用正則分析生成輸出的xml文件。 對不同網站有可能需要通過修改正則來處理不同頁面內容。看完後我在自己的apache上试验通过,下一步是试试不同的网站。自己雖然是多年程序員,但都是数据库、cs架构的,從來沒接觸過web這部分。下面的问题还请站长解答:
1. 如何自动执行php?是使用crontab吗?还是通过一个主php?
2. 访问权限的问题,php不能让所有人访问,生成的xml的访问权限也因应不同进行设置,这部分如何解决?再次感谢!
已回复邮箱。贴在这里可能帮助到别人
/(<article.*?>)(.*?)(<\/article>)/按你的要求,需要明白这两个用法(零宽断言):
(?=exp) 匹配exp前面的位置不包括exp本身
(?<=exp) 匹配exp后面的位置不包括exp本身而上面的正则其实是这样的:
/(exp)(.*?)(exp)/
只是进行了分组,它是包括exp本身的。所以消不掉。(当然,你已经把它分组了,也可以用一个替换得到想要的内容)但是这个又不能这么写
/(?<=<article.*?>)(.*?)(?=<\/article>)/
因为零宽断言不能含有通配符可以这样匹配:
/<header class=”entry-header”>.*?(?=<\/article>)/
也就是紧贴着article标签的header开始(包括header)到</article>为止(不包括</article>)
其实也不必为这些标签烦恼。我试过,标签不配对问题都不太大。多一个少一个的不用纠结。我试了试你的代码,下载链接好像没问题,抱歉了,帮不到。最近再弄澎湃网http://www.thepaper.cn/的全文输出,似乎有点问题,烦请博主有空做个全文RSS造福大家。
你好,能做一个懂球帝头条的全文输出码?http://www.dongqiudi.com/?tab=1
最近發現用Simple HTML DOM Parser(http://simplehtmldom.sourceforge.net/)比正則來得簡單好用,站長可以試試。
PS: 站長能否教下如何弄微博的RSS輸出,微博需要登錄,自己試了些教程,總是有問題,先謝謝了。
楼主太厉害了!!!能不能帮做个冷笑话的 rss
网址http://lengxiaohua.com/非常感谢,终于可以比较方便的自己做rss源了,期待后面教程的更新。
感谢楼主分享,感觉还是有点难度。。。直接用你的吧嘿嘿
先说一声谢!
一直喜欢rss阅读方式!很高兴遇见你!呵呵我有一个国外的服务器,新建一个站点,然后我将你这上面的两个文件放在里面。初步能得到XML的文件。现在咨询一下,如何能让这两个文件自动更新。能读到最新的文件呢。设置自动刷新吗?我是VPS。再就是关于这个墙的问题,在国外存到服务器上是不经过墙的所以这个没问题。我们这边的电脑通过RSS订阅软件拉取数据时。拉过来的是XML格式的国内外的文档。这个墙是如何辨别的?HTTPS能保护服务器和域名吗?我是担心我服务器IP别被封了。感谢有空答复。谢谢。
还有一个咨询问题,有些国外网站上面的图片在国内是看不到的,我看你 个站点上说存到你的服务器上面,复杂不。我服务性能高些,我想试试能不能放我服务器上。看看效果。谢谢
这样一个网站:
原网址:http://www.qhrb.com.cn/organ/organsee/ 我做下令规则space.php如下:<?php
include "gethtml.php";
$regex_link = '/(?<=<a href=").+?(?=")/s';
$regex_tit = '/(?<=)(.+?)(?=)/s’;
$regex_con = ‘/.*?(?=)/s’;
$header=’期货日报’;
$footer=”;
$html=gethtml(‘http://www.qhrb.com.cn/organ/organsee/’);
if(preg_match_all($regex_link, $html, $links)){
$size=count($links[0]);
for($i=0;$i<$size;$i++){
$link=preg_replace('.+','$1',$links[0][$i]);
$content=gethtml($link);
preg_match($regex_con,$content,$article);
preg_match($regex_tit,$content,$title);
$rss.='’.$title[0].”;
}
file_put_contents(‘qhrb.xml’,$header.$rss.$footer);
}
?>不知道问题出在哪里,麻烦指点一下,万分感谢!
链接,标题,内容分别是这样的正规则:
$regex_link = ‘/(?<=<a href=").+?(?=")/s';
$regex_tit = '/(?<=)(.+?)(?=)/s’;
$regex_con = ‘/.*?(?=)/s’;
在NOTEPAD++里面我能定位到他们。
就是后面的那个:
$html=gethtml(‘http://www.qhrb.com.cn/organ/organsee/’);
if(preg_match_all($regex_link, $html, $links)){
$size=count($links[0]);
for($i=0;$i<$size;$i++){
$link=$links[0][$i];
$content=gethtml($link);
preg_match($regex_con,$content,$article);
preg_match($regex_tit,$content,$title);
$rss.='’.$title[0].'<![CDATA['.$article[0].']]
链接不知道如何弄出来,您上面的是相对地址,这个是绝对地址。我测试了几个方法也找不出。再次感谢。我发现问题了,您这个网站把我一些代码过滤掉了。我把我写的源码放这里:http://qhlt.cn/thread-4791-1-1.html 麻烦您帮我看看是哪里的问题,十分感谢。
万分感谢,搞定了。现在还有一个小技术问题,就是如何让这个space.php的文件定时运行一下,好查有没有新的资讯更新。我看你在有些文章中说用CURL类的,具体怎么个弄法?
今天下午费了老长的时间弄这个批量执行计划,我是WIN 的VPS 弄了好半天也没有成功,希望这个网站不要有什么限制。
我晚上也做了几个放上面了,有些能执行,有些执行错误,我看说明是超时,我想是否可以在提取数据时设一限制。比方说一次只取最新的20个。一次执行时提取的数据少一些。是不是就不会出现这种超时的问题了。
今天做新浪网的RSS时出现了一点问题,这个是我问题的链接:http://qhlt.cn/thread-4791-1-1.html 您的网站过滤源码,所以我就发到我论坛上面了。有空麻烦您看一下,看看有没有处理方法。 就是链接提取时出现了一些不想要的链接。十分感谢。
十分感谢,新浪的至少能提取出新闻了。现在我就考虑有没有好的项目呢,这个RSS资讯自己或小满园看还行,一多就容易出现侵权的问题,同时墙的问题也一直存在。我是做投资的。设想是做一个类似的新闻信息聚合,看看有没有市场。现在先自己弄着玩吧。感谢这几天的指导,我也弄了一个小站,已经加你友情链接,有空多交流:)
做这个的人好少啊。最近遇到一个问题,咨询一下,我抓的经常出现只有标题没有内容,或连标题也没有,当然内容也没有了。我用的是quiterss订阅,双击能看到原网址确实有内容,同时通过正规则我发现并没有什么问题。我用的是https://cron-job.org 这个定期刷新的。您经验多,有没有解决方法,十分感谢。
本来想研究一下的,然而完全看不懂~
这是我做的一个论坛的RSS输出。现在的问题是一对一对的输出,在列表截链接时出现了一点问题,麻烦有空帮我看看能解决不。http://qhlt.cn/thread-6447-1-1.html 这个是问题的详细,这里回复会过滤一些源码,所以我放到一个贴子里面了。这个论坛是用DISCUZ 7.2做的。
这个是我做的RSS的地址:http://rssft.com/qhlt/index.xml
十分感谢楼主分享教程,我在vultr新建了个网站,php版本5.2,上传了这两个文件,运行没有反应哪?也不能生成xml文件。能是什么原因哪?
可以试试第三方的自动RSS全文输出网站。https://feedocean.com,它的全文输出基于goreadly项目:https://github.com/antchfx/goreadly
这几天我做金融街的RSS出现了些问题,麻烦帮我看一下我错在哪里了:http://www.qhlt.cn/thread-12656-1-1.html 按之前的注意事项检查了好多遍也没有看出问题所在。因为你这个网站过滤一些代码。所以我贴到一个论坛上面了。方便时加我一下QQ:95527664
刚才发给你回复了,不知道收到没有。
刚才想咨询一下我做的这个RSS出现了些问题。想给你发个地址,帮着看一下,发现你这里不能贴地址了。我怎么加你呢。要不您加我QQ:95527664 或您向我邮箱发一下您的微信,刚才我给您转了9块。那个微信不是我的,不过也可以联系到我。
是可以贴地址的,超过两个或因为一些其它规则才会去垃圾箱,我是能看到的。我会抽空看一下。
另外,小事一桩,无需付费……你用的是不是海外服务器,好像它给禁了,我用了代理是可以抓到的,去掉代理就不成,会超时,基本抓不到东西,不过好解决,它的手机端是没禁用墙外浏览的。
对比一下PC端的链接和手机端的链接:
http://futures.jrj.com.cn/2018/04/16112124394219.shtml
http://m.jrj.com.cn/madapter/futures/2018/04/16112124394219.shtml
要把得到$link稍做修改:
$link=preg_replace(‘#http://futures.jrj.com.cn(.+)#’,’http://m.jrj.com.cn/madapter/futures$1′,$link);
所以后面的抓取是要依据http://m.jrj.com.cn/madapter/futures/2018/04/16112124394219.shtml来进行,相信到这儿应该明白了吧。还有个好处就是页面更轻盈了,抓取负担会小很多,所以基本上只要有手机端页面的我肯定会去抓手机端的。
好的,谢谢,我弄一下,我是海外的服务器,呵呵
有没有班办法抓取微信公众号文章