Thursday, August 28, 2008

Blogger Feed 地址被封?

之前用 Blogger Feed 的 JSON 回调功能实现了侧边栏的“最近评论列表”,后来在把页内评论表单改成 AJAX 方式的时候,也顺便把文章下方的评论改用 AJAX 异步获取了,这样在提交评论后可以立即显示出来,而不用等待 Blogger 通过 FTP 发布重建页面。

可是最近一段时间,发现这两处的评论列表都出现了问题,显示时好时坏,到后来就直接停止工作了(一直显示 Loading Comments...)。而且,在访问了我的 blog 地址的一段时间内,无法打开 www.blogger.com 域名下任何页面。但是如果使用代理,则以上问题都不存在。所以我想大概是 Blogger 的 Feed 地址被封了。

Google 了很久也没看到有类似的案例,因为作为 Blogger 的用户,BlogSpot 和自定义域名的 blog 上,feed 是可以正常访问的。但是对于本站这种 FTP 发布的来说,就只能依赖 http://www.blogger.com/feeds/... 这个地址了。估计是国内用 Blogger FTP 发布的 Blog 并不多,也很少有依赖 feed 地址来实现功能的,所以也就没太关注这个问题吧。通过 Google 找到另一个用 Blogger FTP 发布的例子,mixfog,细研究下发现博主完全摒弃了 Blogger 的评论系统,自己实现了一套评论,可以自动获取并显示评论者留下的 URL 的 favicon,还可以回复评论,真是有心啊……

为了解决这个问题,我寻思了好久都没有找到办法。因为打开评论的 feed 地址是在 JavaScript 调用的,因此要求所有的访问者都能访问这个地址才行。我试过写一个中转的 PHP 程序在服务器上来获取内容再直接返回,可在服务器上实验时直接返回了 404,看来在国内是没办法访问到的了。

今天突然想起来如果能够在国外的网站上做这样一个中转,就可以解决了,于是问了下朋友 liuming,把中转的 PHP 页面放到他的 DreamHost 主机上,于是问题就解决了…… 在此深表谢意!郁闷了好久的问题终于解决了。

顺便说句题外话,DreamHost 上 500G 空间、可开无数独立站、每月流量限制 5T 的虚拟空间,一年才 119 美元,看样子比我在国内租的合租服务器划算多了啊…… -_-bb

Labels: , ,

Thursday, May 29, 2008

用 AJAX 实现 Blogger 页内评论

之前服务器上有 Java 环境时,一直用一个自己写的 Servlet 作为中间代理来向 Blogger 的评论页面 POST 表单数据,实现页面内的评论操作,后来转挂在朋友的 IIS 服务器下,由于对 ASP 不熟,这一功能就一度取消了。现在购买了新的 Linux PHP 服务器,因此用 PHP 重新写了一个同样功能的中间代理来实现这一功能,并且实现成了 AJAX 的模式。评论内容的读取也一样通过 Blogger Feed 的 JSON 模式读取,因此提交评论后可以立即显示出来,而不用再等待 Blogger 重新生成 HTML 页面并通过 FTP 上传这一漫长的过程。(虽然实际上后台它还是不可避免的执行了这个过程。)

经过多次测试,应该可以用了。关于 Spam 的问题,以前的验证码是直接读取的 Blogger 页面的 Captcha 图片,现在 Google 改变了表单结构以至于程序已经无法自动做这个动作。所以我取消了 Blogger 自己的 Captcha 验证,自己写了个简单的加减法验证,虽然仍然不能完全杜绝 Spam,但已经比几天前测试时裸奔的情况好多了。当时夸张到一个下午一张帖子被贴了 50 多条 Spam 评论。毕竟传说 Google 的 Captcha 也已经被破解了么,同样不能完全杜绝 Spam。 ;-)

另外,Backlink 不显示的问题也修正了。不过,经过前端时间页面恶意代码事件的影响,目前似乎已经没什么 Backlink 了…… :-(

Labels: , , , , , , ,

Friday, January 05, 2007

用 JSON 实现侧边栏的最新评论列表

上个月 21 号 Google 发出消息,声称 GData API 开始支持以 JSON (JavaScript Object Notation,中文介绍) 的形式提供数据,并且给出了对应的 API 文档,同时 Blogger Buzz 网站也告知广大用户,JSON 支持的 GData API 中同样也包括 Blogger。

在这之前,由于 JavaScript 先天的限制,我们不能通过 JavaScript 代码打开当前域以外的远程文件,这也就限制了我们通过传统的 AJAX 技术利用 GData API 的 Atom Feed 来实现 Blogger 页面上最新帖子、评论列表的即使更新,因为我们无法在某个 *.blogspot.com 域名下打开 www.blogger.com 下的 XML 文档。当然,新的 Blogger 支持在自己的域名下,也就是以 yourname.blogspot.com/feeds/ 的形式访问 Atom Feed 解决了这个问题,但是对于通过 FTP/sFTP 发布的非 blogspot 用户,还是无法绕过这个问题。

现在,Google GData API 除了可以在原来的地址后面加 alt=json 参数来以 JSON 的格式组织数据以外,还可以用 alt=json-in-script&callback=myFunction (其中 myFunction 是自己用来处理 JSON 数据的函数) 的方式使得 Feed 返回的 JS 代码内容直接是对 myFunction 函数的调用,这样就绕过了以上 JavaScript 不能远程调用本域以外资源的限制。

通过这个办法,我修改了自己 Blogger 侧边栏的最新评论列表。虽然原来有一个,不过只是根据 Blogger Help 上的这篇介绍开启的,原理还是利用 <Blogger> 标签的循环,只输出评论的部分,也就是说,原来的方法输出的只是当前页面最新评论列表,没有在首页列出的文章,其评论是不会出现的。而且,在默认情况下,评论的排序方式是先按帖子先后顺序,再按时间顺序。我自己另外写了一个 JavaScript 函数来对它们重新排序,并只保留最新的 10 条。

现在,通过 GData API 的 JSON 回调支持,我写了一个真正意义上的最新评论列表。看到这位网友提供了一个 blogspot 用户适用的办法,对于非 blogspot 发布,特别是 FTP/sFTP 发布的用户,可以用我的办法:

<div id="sidebar-recent-comments">
<p id="comment-loading">Loading Data...</p>
<dl id="comments-block">
<dt class="comment-data" name="comment-data">
<a href=""></a><span>, </span>
<span class="comment-poster">
<a href="" rel="nofollow"></a></span>
<span> said...</span></dt>
<dd class="comment-body" name="comment-body"><p></p></dd>
</dl></div>

<script type="text/javascript">

// Fetch the recent comments from Blogger Feed with JSON code and
// the callback func is "dispComments".
function getComments(blogId, counts) {

// Temporarily hide it
var dl = document.getElementById("comments-block");
dl.style.display = "none";

// Retrieve the JSON feed.
var script = document.createElement('script');
script.setAttribute('src', 'http://www2.blogger.com/feeds/' + blogId +
'/comments/default?alt=json-in-script&callback=' +
'dispComments&start-index=1&max-results=' + counts);
script.setAttribute('id', 'jsonScript-recent-comments');
script.setAttribute('type', 'text/javascript');
document.documentElement.firstChild.appendChild(script);
}

// Translate the date
function transDate(dateStr) {
dateStr = dateStr.substring(0, dateStr.indexOf("."));
dateStr = dateStr.replace("T", " ");
dateStr = dateStr.replace(/\-/g, "/");
return dateStr;
}

// Display the comment entries onto the web page.
function dispComments(json) {
var dl = document.getElementById("comments-block");

// get entry template
var dt = dl.getElementsByTagName("dt")[0];
var dd = dl.getElementsByTagName("dd")[0];

dl.removeChild(dt);
dl.removeChild(dd);

for (var i = 0; i < json.feed.entry.length; i++) {
var entry = json.feed.entry[i];
var curDt = dt.cloneNode(true);
var curDd = dd.cloneNode(true);

// Time
curDt.childNodes[0].href = entry.link[0].href;
curDt.childNodes[0].appendChild(
document.createTextNode(transDate(entry.published.$t)));

// Author
curDt.childNodes[2].childNodes[0].appendChild(
document.createTextNode(entry.author[0].name.$t));
if (entry.author[0].uri) {
curDt.childNodes[2].childNodes[0].href = entry.author[0].uri.$t;
}
else {
curDt.childNodes[2].childNodes[0].removeAttribute("href");
}
dl.appendChild(curDt);
dl.appendChild(curDd);

//Content
curDd.childNodes[0].appendChild(
document.createTextNode(entry.title.$t));
}

dl.style.display = "block";
var commentLoading = document.getElementById("comment-loading");
commentLoading.style.display = "none";
}

getComments('yourBlogId', entryCount);
</script>

注意最后一行调用的 getComments 函数的两个参数,yourBlogId 是你当前这个 Blog 的 blogId,每个 Blog 都是不同的。打开自己帖子的评论页面,从 URL 上就可以找到自己的 blogId。第二个参数 entryCount 是要显示的评论条数,例如 10。

另外,为了保持页面整洁,我只使用了评论的第一行,也就是 title 部分的内容。如果需要显示完整,将以上代码中蓝色的 title 改成 content 即可。

为了简洁起见,也可以把 getComments 和 dispComments 两个函数放到外部的 .js 文件中去定义,页面只用引入这个 .js 文件,然后调用 getComments 即可。

Labels: , , , ,

Saturday, November 18, 2006

通过 GData API 提交评论

前两天有提到升级到 Blogger Beta 后发布评论的问题。今天从 Google Groups 上的 Google Data API 讨论组上看到一个新的发布评论的办法,就是用 GData API 通过单贴评论的 Feed 地址
http://beta.blogger.com/feeds/blogID/postID/comments/default

发布。

这个方法与向 http://beta.blogger.com/comment.do 直接 POST 数据的方法比起来,要科学得多。经过测试,这个方法确实可行,评论发布后,页面会被正常地重建。然而,仍然有问题:评论对应的发布者被设置成了 Blogger 的主人,也就是在向 feed POST 数据之前提供给 Google 的身份验证信息对应的用户。

据讨论组上 Blogger 的研发人员回复说,官方并不支持这种方法提交评论,尽管它确实是可行的。我想之所以会有上面的问题,大概是因为这个方法原本是用来发布帖子用的,在这种情况下,作者信息自然就应该从通过身份验证的 Blogger 账户中取得。

已经在这个有关 GData API 提交评论的讨论串中提出建议修正这个问题,不过不知道 Blogger 会不会理我。在这个问题被修正之前,这个方法实际仍然无法投入实用,毕竟不会有人会让所有评论的作者信息丢失掉。

Labels: , , , ,

Wednesday, November 15, 2006

Feeds of Blogger Beta

今天爬 Blogger Beta 的资料,发现 Blogger Beta 除了可以提供整站帖子、整站评论以及分帖子评论的 feed 以外,甚至可以按照单个的 label 来提供 feed,格式如下:
http://beta.blogger.com/feeds/blogID/posts/default/-/labelname

URL 中的 labelname 就是要订阅的 label,注意中间的“-”符号不能少!

另外,把其它的订阅地址的格式也一并写在这里:

订阅整站帖子全文:
http://beta.blogger.com/feeds/blogID/posts/full

订阅整站帖子默认,即按照 Blogger 的 Site Feed 设置选项:
http://beta.blogger.com/feeds/blogID/posts/default

订阅整站评论:
http://beta.blogger.com/feeds/blogID/comments/default

订阅单贴评论:
http://beta.blogger.com/feeds/blogID/postID/comments/default


Update on 2006/11/17:
对于 label 的 Feed,发现如果 labelname 中含有空格,则无法正确获取 Feed 内容,会出现 Blogger 的“We're sorry, but we were unable to complete your request.”报错页面,例如:
http://beta.blogger.com/feeds/blogID/posts/default/-/Knowledge Base

无论中间的空格是否被 urlencode 成 %20,都会出现这个情况。已经向 Blogger GData API 讨论组 提交了这个问题,不过至今仍未有任何回复。

Update on 2007/01/12:
这个问题在 Blogger GData API 的另一个讨论串中被再次提到,并被认定为一个 bug,可以通过这里来追踪。希望这个问题能够早日得到解决。

Labels: , , , ,

Monday, November 13, 2006

升级后如何才能方便的发布评论?

升级到 Blogger Beta后,由于大家无法访问 beta.blogger.com 域名,因此出现了无法发布评论的问题,在上次的帖子中有所讨论。

为了解决这个问题,我自己写了个简单的 Servlet,来接受来自页面上的评论发布,并将这个请求转到 Blogger Beta 上处理评论发布的地址 https://beta.blogger.com/comment.do,因为我可以修改服务器上的 host 文件使其可以访问 beta.blogger.com,这样可以起到一个类似代理的作用,代替需要发布评论的朋友们访问这个不能直接访问的域名。

理论上是没有问题的,实践上我也几乎取得了成功。出现的问题是:评论被正常发布后,和评论相关的帖子页面没有重建!

我们知道,用 FTP 的方式发布 Blogger,任何对帖子的更改,都会导致 Blogger 自动重建页面并自动发布到 FTP 相关的目录下,以使得 blog 网站上的页面能够反应出最近的信息,这些操作包括新增/修改/删除帖子,以及添加/删除评论。正常情况下,一旦有评论发布,这个重建的过程就会发生,这样评论能够在最多几分钟的时间内出现在页面上。

可是现在,评论的内容都出现在 Blogger Beta 自己的评论页面上了,但是却没有触发页面重建。不过,如果直接把页面上评论表单的内容提交到 https://beta.blogger.com/comment.do,则一切正确;但是当然这样做没有意义,因为这要求发布评论的朋友能够直接访问 beta.blogger.com 域名。

现在出现的现象会是,大家发布的评论不会立即显示在帖子页面上,但是实际上是已经被正确的保存了。我看到电子邮件的提示后,就会尽快重建页面使得这些评论能够被显示出来。相信这个问题只是暂时的,总归是应该得到解决的。

这个问题琢磨了一晚上也没有得到结果,Google 上也搜不出什么有用的东西来。已经把这个问题发布到了 Google 上的 Blogger Data API 讨论组求助,希望有人遇到过类似的问题从而给我一些提示。

Updated on 2006/11/17:
有一个更科学的方法来提交评论,那就是用 GData API 向单贴评论的 Feed 地址提交,不过仍然有些问题。详见“通过 GData API 提交评论”。

Updated on 2006/12/21:
Blogger 的某次更新似乎已经解决了评论提交后页面不会重建的问题。现在在页内的评论表单中提交评论,页面会被立即重建,只是由于需要重建的页面和以往的老 Blogger 比起来要多一些,因此会慢一点。一般 5 分钟之内评论就会出现在页面上了。

Labels: , , , , ,