csdn论坛公开了一些常用api,不过内部测试阶段,地址是http://forum.csdn.net/OpenApi/forumapi.asmx还有一个使用的demo,http://forum.csdn.net/OpenApi/ForumOpenAPIDemo.rar,源码在这里下载demo源码
总体概述:
公开的方法如下:
至于获得帖子和获得帖子列表的方法,虽然没有提供独立的api,但是都可以借助论坛现有的资源,待会会单独讲到
上面的API除了GetForums外,都需要输入一个identity实体,表明你的身份,返回了一个bool型变量,表示操作是否完成,结果会以out变量的形式输出,同时输出的一般还有错误信息Error
identity的参考定义如下
///
<summary>
///
用户身份信息
///
</summary>
public
struct
Identity{
///
<summary>
///
用户名
///
</summary>
public
string
username;
///
<summary>
///
密码
///
</summary>
public
string
password;
}
他包含用于身份验证的用户名和密码,除获得论坛列表以外,其他的操作均要求此参数,调用者可以将用户信息加密存与本地,详细请参考账户管理
而错误信息的参考定义如下
///
<summary>
///
错误信息
///
</summary>
public
struct
Error
{
///
<summary>
///
错误id
///
</summary>
public
int
errId;
private
string
_errInfo;
///
<summary>
///
错误信息
///
</summary>
public
string
errInfo;
///
<summary>
///
描述
///
</summary>
public
string
description;
}
这个实体存放了调用过程中返回的错误,如果返回结果为false,我们就可以查看或者错误信息:
比如下面的积分捐赠的代码段
Identityid
=
dp.GetDefaultAccount();
Errorerror;

if
(
!
openApiService.PointDonate(dp.GetDefaultAccount(),tbUserName.Text,point,
"
abc
"
,
out
error))
ErrorForm.ShowDialog(error);
else
MessageBox.Show(
"
捐赠成功
"
);
GetForums 非常的简单,没有传入参数,方法的返回值是一个Forum实体数组
Forum的参考定义和具体字段含义如下
///
<summary>
///
论坛信息
///
</summary>
public
struct
Forum
{
///
<summary>
///
论坛id
///
</summary>
public
GuidforumId;
///
<summary>
///
父论坛id
///
</summary>
public
GuidparentForumId;
///
<summary>
///
论坛名称
///
</summary>
public
string
name;
///
<summary>
///
别名
///
</summary>
public
string
alias;
///
<summary>
///
是否技术论坛
///
</summary>
public
bool
IsTech;
///
<summary>
///
版主
///
</summary>
public
string
[]morderators;
///
<summary>
///
积分归属论坛
///
</summary>
public
GuidpointBelongsToForumId;
}
方法定义如下:
///
<summary>
///
获得用户信息
///
</summary>
///
<paramname="identity">
用户身份信息
</param>
///
<paramname="profile">
用户信息
</param>
///
<paramname="error">
错误信息
</param>
///
<paramname="username">
需要获得用户信息的用户名
</param>
///
<returns>
操作是否成功
</returns>
public
bool
GetUserProfile(Identityidentity,
string
username,
out
UserProfileprofile,
out
Errorerror)
此方法用于查询某用户的用户信息,包括用户昵称,可用分,用户技术专家分,非技术专家分,以及他在各个论坛的得分和级别(只展示用户在其有得分的论坛信息)
用户信息UserProfile的参考定义和字段含义如下
public
struct
UserProfile
{
///
<summary>
///
可用分
///
</summary>
public
int
point;
///
<summary>
///
技术专家分
///
</summary>
public
int
techExpertPoint;
///
<summary>
///
用户在各个论坛的积分和级别信息
///
</summary>
public
List
<
TopForum
>
topForums;
///
<summary>
///
非技术专家分
///
</summary>
public
int
nonTechExpertPoint;
///
<summary>
///
昵称
///
</summary>
public
string
nickName;
///
<summary>
///
用户名
///
</summary>
public
string
username;
}
///
<summary>
///
用户在各个论坛的积分和级别
///
</summary>
public
struct
TopForum{
///
<summary>
///
论坛
///
</summary>
public
GuidforumId;
///
<summary>
///
专家分
///
</summary>
public
int
expertPoint;
///
<summary>
///
星级
///
</summary>
public
string
rank;
}
发帖Post :
发帖方法定义如下
/**/
///<summary>
///发帖
///</summary>
///<paramname="identity">用户身份证</param>
///<paramname="post">帖子</param>
///<paramname="error">错误信息</param>
///<paramname="topicUrl">帖子链接</param>
///<returns>发帖是否成功</returns>
public
bool
Post(Identityidentity,Postpost,
out
Errorerror,
out
string
topicUrl)
Post结构参考定义
///
<summary>
///
帖子
///
</summary>
public
struct
Post
{
///
<summary>
///
论坛id(发帖时必须)
///
</summary>
public
GuidforumId;
///
<summary>
///
标题(发帖时必须)
///
</summary>
public
string
subject;
///
<summary>
///
帖子内容(发帖时必须)
///
</summary>
public
string
body;
///
<summary>
///
标签
///
</summary>
public
string
tag;
///
<summary>
///
给分
///
</summary>
public
int
point;
///
<summary>
///
是否问专家贴(发帖时必须)
///
</summary>
public
bool
isAskExpert;
///
<summary>
///
专家用户名称(若isAskExpert,必须)
///
</summary>
public
string
expertUserName;
///
<summary>
///
编辑器类型(发帖时必须),现只支持ubb类型
///
</summary>
public
EditorTypeeditor;
///
<summary>
///
帖子链接
///
</summary>
public
string
url;
}
回帖Reply :
/**/
///<summary>
///回复帖子
///</summary>
///<paramname="identity">用户身份证</param>
///<paramname="reply">回复</param>
///<paramname="error">错误信息</param>
///<paramname="replyId">回复id</param>
///<paramname="layer">楼层</param>
///<returns>回复是否成功</returns>
public
bool
Reply(Identityidentity,Replyreply,
out
Errorerror,
out
long
replyId,
out
int
layer)
回复实体参考定义如下
///
<summary>
///
回复
///
</summary>
public
struct
Reply
{
///
<summary>
///
论坛id(必须)
///
</summary>
public
GuidforumId;
///
<summary>
///
帖子url(必须)
///
</summary>
public
string
topicUrl;
///
<summary>
///
回复内容(必须)
///
</summary>
public
string
body;
///
<summary>
///
是否需要ubb(必须)
///
</summary>
public
EditorTypeeditor;
}
///
<summary>
///
结贴
///
</summary>
///
<paramname="identity">
用户身份证
</param>
///
<paramname="topicUrl">
帖子链接
</param>
///
<paramname="forumId">
论坛id
</param>
///
<paramname="replyPoints">
回复给分列表
</param>
///
<paramname="error">
错误
</param>
///
<returns>
结贴是否成功
</returns>
public
bool
CheckOutTopic(Identityidentity,
string
topicUrl,GuidforumId,List
<
ReplyPoint
>
replyPoints,
out
Errorerror)
List<ReplyPoint> replyPoints为回复id和给分数组
///
<summary>
///
回帖得分
///
</summary>
public
struct
ReplyPoint
{
///
<summary>
///
回复id
///
</summary>
public
long
replyId;
///
<summary>
///
得分
///
</summary>
public
int
point;
}
///
<summary>
///
可用分捐赠
///
</summary>
///
<paramname="identity">
用户身份证
</param>
///
<paramname="toUser">
捐赠对象
</param>
///
<paramname="point">
捐赠积分
</param>
///
<paramname="reason">
原因
</param>
///
<paramname="error">
错误
</param>
///
<returns>
捐赠是否成功
</returns>
public
bool
PointDonate(Identityidentity,
string
toUser,
int
point,
string
reason,
out
Errorerror)
///
<summary>
///
获得我发表的帖子,我回复过的帖子,我得分的帖子
///
</summary>
///
<paramname="listType">
列表类型
</param>
///
<paramname="forumId">
论坛id
</param>
///
<paramname="posts">
帖子列表
</param>
///
<paramname="error">
错误信息
</param>
///
<paramname="identity">
身份信息
</param>
///
<returns>
是否成功
</returns>
[WebMethod]
public
bool
GetTopicsOfUser(Identityidentity,UserTopicListTypelistType,GuidforumId,
out
List
<
Post
>
posts,
out
Errorerror)
列表类型定义如下
///
<summary>
///
用户帖子列表类型
///
</summary>
public
enum
UserTopicListType
{
///
<summary>
///
用户的帖子
///
</summary>
TopicOfUser,
///
<summary>
///
用户回复过的帖子
///
</summary>
TopicUserJoined,
///
<summary>
///
用户得分的帖子
///
</summary>
TopicUserRewarded,
///
<summary>
///
所有问专家
///
</summary>
AllAskExpert
}
获得帖子列表
获得帖子列表,包括
待解决
抢分区
零回复
热点区
已解决
精华区 没有提供独立的Webservice,原因是这些帖子列表均提供了Rss,调用者通过Rss获得需要的信息
一个列子列表的rss链接由论坛别名和列表类型两部分组成
比如灌水乐园抢分区的Rss链接为http://forum.csdn.net/Rss/FreeZone/RobPointList/
其中黄色部分(FreeZone)为论坛别名,红色部分(RobPointList)表明列表类型为抢分区,我们可以通过如下代码简单实现取得rss并转为dataset
public
DataTableGetTopicListRss()
{
string
url
=
"
http://forum.csdn.net/Rss/FreeZone/RobPointList/
"
;
HttpWebRequestrequest
=
HttpWebRequest.Create(url)
as
HttpWebRequest;
WebResponseresponse
=
request.GetResponse();
DataSetresult
=
new
DataSet();
StreamrssStream
=
response.GetResponseStream();
StreamReadersr
=
new
StreamReader(rssStream,Utility.GetEncoding());
result.ReadXml(sr);
return
result.Tables[
2
];
}
获得与解析帖子
公开的API也没专门获得帖子的方法,主要是处于性能的考虑,想要获得帖子,就直接获取帖子html文件,如果需要帖子的信息,比如发帖人,分数,就必须解析帖子文件,文件中提供了一系列标识(csdnid),让解析者可以通过其找到对应的内容,并且在所附demo中,也提供了一个经过改造的解析模块,调用者可以使用这个模块,通过csdnid来找到帖子文件中具体的内容
什么是csdnid?
打开任意一个帖子文件,里面都会看到一些由csdnid标识的元素,这些元素的属性和内容一般都具有特殊的意义,比如帖子源文件中的下面html代码
<
meta
id
="topicViewUrl"
csdnid
="topicViewUrl"
content
="http://topic.csdn.net/u/20080328/15/ce3f9a96-7f91-4dea-83fb-23beffe36cb8.html"
>
<
meta
csdnid
="sectionId"
content
="a3049f56-b572-48f5-89be-4797b70d71cd"
>
csdnid="topicViewUrl" 的meta元素的content属性,说明了帖子的url,为:http://topic.csdn.net/u/20080328/15/ce3f9a96-7f91-4dea-83fb-23beffe36cb8.html
而csdnid="sectionId"的meta元素的content属性,说明了帖子的论坛id为:
a3049f56-b572-48f5-89be-4797b70d71cd
而<var csdnid="topicUsername" id="topicUserName">Orange1997</var>中,此元素的innerHTML为发帖用户名
如何解析帖子文件并得到我们想要的信息
解析html文件有很多方法,这里使用使用经过改进的开源html解析其HtmlAgilityPack,Demo中有此模块,
基本使用方法
加载Html文件
下面方法可以把某个html加载进来
HtmlDocument d = new HtmlDocument();
d.Load("C:\test.html");
Load方法还有多个重载,可以从Stream,StreamReader等对象中加载html文档
加载后使用GetElementsbyCsdnId来获得指定csdnid标识的元素,比如
d.GetElementsbyCsdnId("topicBody"),获得所有用csdnid="topicBody"标识的元素
注意这里的返回值是一个元素数组,因为csdnid和id属性不同,是可以重复的;
下面的代码是demo中用于解析帖子文件的方法,详细使用请看demo源码
private
InternalTopicParseFile(StreamReaderreader){
InternalTopicpost
=
new
InternalTopic();
HtmlDocumentd
=
new
HtmlDocument();
d.Load(reader);
post.body
=
((HtmlNode)d.GetElementsbyCsdnId(
"
topicBody
"
)[
0
]).InnerHtml;
post.forumId
=
new
Guid(((HtmlNode)d.GetElementsbyCsdnId(
"
sectionId
"
)[
0
]).Attributes[
"
content
"
].Value);
post.subject
=
((HtmlNode)d.GetElementsbyCsdnId(
"
topicSubject
"
)[
0
]).InnerHtml;
post.point
=
color
分享到:
评论