留意到 WordPress 的后台默认会调用几个 RSS 地址,通过分析得知其使用了 MagpieRSS, 核心文件为 wp-includes/rss-functions.php 。我们增加链接的时候,可以同时提供 RSS 地址,那么我们完全可以通过这个 RSS 地址在我们的日志上直接阅读 RSS 内容。这里有一段理论性的代码,请参考后面的 get_list_of_rss() 函数。 另外,MagpieRSS 只是 RSS 分析器,本身并不提供 RSS 发掘功能,在应用了该分析器的诸多开源程序中,注意到有 Gregarius, 一款很不错的 RSS 聚合程序。如果用过这套聚合程序,就知道在后台添加频道的时候,可以仅提供网址来自动发掘可用的 RSS 地址清单,所以利用这部分程序,我们在没有提供链接的 RSS 地址的情况下,也可以自动分析出 RSS 地址,然后调用 get_list_of_rss() 函数。MagpieRSS 中该部分代码在 util.php 中,主要是 getUrl() 和 extractFeeds() 两个函数。我将其放到 WordPress 下的 rss-functions.php 文件中使用。 getUrl() 和 extractFeeds() PHP: /********************************************/ /********************************************/ /** * Fetches a remote URL and returns the content */ function getUrl($url, $maxlen = 0) { //Bug: in windows, scheme returned by parse_url contains the drive letter //of the file so a test like !isset(scheme) does not work //maybe it would be better to only use is_file() which only detect //local files? $urlParts = parse_url($url); if (@is_file($url) || (!isset($urlParts['scheme']) && !isset($urlParts['host'])) ) { //local file! $c = ""; $h = @fopen($url, "r"); if ($h) { while (!feof($h)) { $c .= @fread($h, 8192); } } @fclose($h); return $c; } $client = new Snoopy(); $client->agent = MAGPIE_USER_AGENT; $client->use_gzip = MAGPIE_USE_GZIP; if ($maxlen) { $client->maxlength = $maxlen; } @ $client->fetch($url); return $client->results; } /** * Feed Autodiscovery * * returns an array of all (hopefully) rss/atom/rdf feeds in the document, * pointed by $url. * See http://diveintomark.org/archives/2002/06/02/important_change_to_the_link_tag * * @param string $url URL of a web document containing <link> elements * @return array Array of feed URLs */ function extractFeeds($url) { $cnt = getUrl($url); $ret = array (); //find all link tags if (preg_match_all('|<link\s+\w*=["\'][^"\']+["\']+[^>]*>|Uis', $cnt, $res)) { while (list ($id, $match) = each($res[0])) { // we only want '<link alternate=...' if (strpos(strtolower($match), 'alternate') && !strpos(strtolower($match), 'stylesheet') && // extract the attributes preg_match_all('|([a-zA-Z]*)=["\']([^"\']*)|', $match, $res2, PREG_SET_ORDER)) { $tmp = array (); //populate the return array: attr_name => attr_value while (list ($id2, $match2) = each($res2)) { $attr = strtolower(trim($match2[1])); $val = trim($match2[2]); // make sure we have absolute URI's if (($attr == "href") && strcasecmp(substr($val, 0, 4), "http") != 0) { // Check to see if the relative url starts with "//" if(substr($val,0,2) == "//") { $val = preg_replace('/\/\/.*/', $val, $url); } else { $urlParts = parse_url($url); if ($urlParts && is_array($urlParts) && strlen($val)) { if ($val[0] != '/') { $val = '/'.$val; } $val = $urlParts['scheme'] . '://' .$urlParts['host'] . $val; } else { $val = ($url.$val); } } } $tmp[$attr] = $val; } $ret[] = $tmp; } } } return $ret; } 使用方式(显示列表) PHP: $url = 'http://ulysses.cn/'; $feeds = extractFeeds($url); if (!is_array($feeds) || sizeof($feeds) == 0) { } else { //if (is_array($feeds) && sizeof($feeds) == 1 && array_key_exists('href',$feeds[0])) { //echo $feeds[0]['href'] . '<br />'; //} else { $cnt = 0; while(list($id, $feedarr) = each($feeds)) { // we need an URL if (!array_key_exists('href', $feedarr)) { continue; } else { $href = $feedarr['href']; } if (array_key_exists('type', $feedarr)) { $typeLbl = " [<a href=\"$href\">" . $feedarr['type'] . "</a>]"; } $cnt++; if (array_key_exists('title', $feedarr)) { $lbl = $feedarr['title']; } elseif (array_key_exists('type', $feedarr)) { $lbl = $feedarr['type']; $typeLbl = ""; } elseif (array_key_exists('href', $feedarr)) { $lbl = $feedarr['href']; } else { $lbl = "Resource $cnt"; } echo "<p>\n\t<input class=\"indent\" type=\"radio\" id=\"fd_$cnt\" name=\"new_channel\" " ." value=\"$href\" />\n" ."\t<label for=\"fd_$cnt\">$lbl $typeLbl</label>\n" ."</p>\n"; //} } } get_list_of_rss() PHP: function get_list_of_rss($link_id) { global $wpdb; $feed = $wpdb->get_row("SELECT link_name, link_url, link_description, link_updated, link_rss FROM `$wpdb->links` WHERE link_id = '$link_id'"); if (!$feed) { return; } else { $link_rss = $feed->link_rss; $link_name = $feed->link_name; _e('<h2 class="pagetitle">' . $link_name . '</h2>'); } $rss = @fetch_rss($link_rss); if ( isset($rss->items) && 0 != count($rss->items) ) { _e('<div class="post">'); $rss->items = array_slice($rss->items, 0, count($rss->items)); foreach ($rss->items as $item ) { ?> <h4><a href='<?php echo wp_filter_kses($item['link']); ?>'><?php echo wp_specialchars($item['title']); ?></a> — <?php printf(__('%s ago'), human_time_diff(strtotime($item['pubdate'], time() ) ) ); ?></h4> <p><?php echo $item['description']; ?></p> <?php } _e('</div>'); } } 使用 PHP: $link_id = (int) $_GET['link_id']; get_list_of_rss($link_id); 能力所限,这里用到的两部分代码,我并没有很好地将其结合在一起,有兴趣的可以考虑实现。 ============================== 原创文章:http://www.purewhite.cn/?p=78 ==============================
补充说明一下: get_list_of_rss() 中的 SQL 语句读取字段较多,本来是想在显示列表的时候同时显示该链接的一些相关信息。 PHP: $feed = $wpdb->get_row("SELECT link_name, link_url, link_description, link_updated, link_rss FROM `$wpdb->links` WHERE link_id = '$link_id'");