笔者比较喜欢看书,经常在豆瓣上闲逛,最近才发现豆瓣提供的api,很有意思,没事时研究了一番,图书的搜索、信息获取和评论获取都很方便,确实是强大的api。
虽然已经有很多很好很强大的基于豆瓣api的应用了,脑中还是不禁浮现了自己动手做一个的念头,例如在windows phone上(还需要学习很多内容,残念╮(╯▽╰)╭)。
言归正传。试验豆瓣api的过程中,发现获取书籍评论时存在一个问题:只能获取到评论摘要,而无法获取评论全文。这点很让人头疼,豆瓣api小组讨论区对此的解答是api不提供评论全文。悲剧,看来得另谋它法了。还好在一则api小组的讨论贴得到启发,也是本文要写的方法:评论的html网页上肯定是包含全文的,尝试着把他抓取出来吧。
一、评论的网页地址
以《Programming Collective Intelligence》这本书为例,使用api调用(http://api.douban.com/book/subject/isbn/9780596529321/reviews?start-index=1&max-results=5,该网址可直接在浏览器中打开,chrome会直接显示xml源内容,ie貌似会显示成RSS样式,⊙﹏⊙b汗,注意未带apikey的调用存在一分钟10次的限制)。返回得到该书的前5条评论信息,我们选取第一条,xml数据如下:
<entry>
<id>http://api.douban.com/review/1480000</id>
<title>实战性极强</title>
<author>
<link href="http://api.douban.com/people/1292376" rel="self"/>
<link href="http://www.douban.com/people/wdgu/" rel="alternate"/>
<link href="http://img3.douban.com/icon/u1292376-6.jpg" rel="icon"/>
<name>clickstone</name>
<uri>http://api.douban.com/people/1292376</uri>
</author>
<published>2008-08-25T21:16:25+08:00</published>
<updated>2010-11-16T10:09:16+08:00</updated>
<link href="http://api.douban.com/review/1480000" rel="self"/>
<link href="http://www.douban.com/review/1480000/" rel="alternate"/>
<link href="http://api.douban.com/book/subject/2209702" rel="http://www.douban.com/2007#subject"/>
<summary>
中国有句老话,叫做“知易行难”。 作算法的朋友应该更有体会,想把 paper 上的公式转变为可以运行的代码,这是件考验功力的事情。 Toby...
</summary>
<db:comments value="13"/>
<db:useless value="1"/>
<db:votes value="41"/>
<gd:rating max="5" min="1" value="5"/>
</entry>
解析出其中<link href="http://www.douban.com/review/1480000/" rel="alternate"/>中的地址http://www.douban.com/review/1480000/,就是该评论的网页地址了。XML的解析这里不展开了,以后得空讨论一下豆瓣api返回的XML的解析。
在此鸣谢一下豆瓣网友clickstone写的精彩评论。
二、获取网页html并分析
浏览器打开评论地址,查看网页的源文件(使用chrome的“审查元素”更方便一些)。发现评论内容是包含在<span property="v:description"> </span>中的如下:
<span property="v:description">
中国有句老话,叫做“知易行难”。
<br/> 作算法的朋友应该更有体会,想把 paper 上的公式转变为可以运行的代码,这是件考验功力的事情。
<br/> Toby Segaran 写的这本《Programming Collective Intelligence》,是修炼此种功力的武林秘笈之一。......(全文省略--笔者注)</span>
可以看出,评论全文中多出了不少html元素,有<br/>,<wbr/>和<a href="....."> </a>。笔者对html不熟,不清楚不去除这些元素在移动应用中显示是否可以。本文要谈的是,获取到去除html元素的文本,我们继续来看。
三、得到全文
这一步应该有多种方法,例如解析html,正则表达式。咱们来讨论正则表达式的方法。想必大家都比我熟悉,我就不废话了,直接上代码吧:
using System;
using System.Text.RegularExpressions;
using System.Net;
namespace ReTest
{
class Program
{
static void Main(string[] args)
{
System.Net.WebClient client = new System.Net.WebClient();
byte[] page = client.DownloadData("http://book.douban.com/review/1480000/");
string rawhtml = System.Text.Encoding.UTF8.GetString(page);
string re1 = "(<span property=\"v:description\">)"; // content header
string re2 = "(.*?)"; // Non-greedy match on filler
string re3 = "(</span>)"; // tail
Regex r = new Regex(re1 + re2 + re3, RegexOptions.IgnoreCase | RegexOptions.Singleline);
Match m = r.Match(rawhtml);
if (m.Success)
{
String content = m.Groups[2].ToString();
//delete html elements
content = content.Replace("<br/> ", "\r\n ");//换行和缩进
content = content.Replace("<br/>", "");
content = content.Replace("<wbr/>", "");
//去除超链接
Regex rhref = new Regex("(<a href=[^>]+>)", RegexOptions.IgnoreCase | RegexOptions.Singleline);
Match mhref = rhref.Match(content);
if (mhref.Success)
{
String shref = mhref.Groups[1].ToString();
content = content.Replace(shref, "");
}
content = content.Replace("</a>", "");
Console.Write(content.ToString() + "\n");
}
}
}
}
四、总结
测试了几个评论网页,效果还蛮不错,希望本文对你有所帮助。获取书籍的网店价格和链接想必也可用此法解决,还没来得及尝试,感兴趣的同学多研究研究。下面的文章很精彩,大家可以参考:C#解析HTML。
哦,one more thing,鸣谢一下正则表达式生成器网站txt2re。以上C#代码是在该网站生成的代码基础上修改的。