曾几何时,你是否也曾有一个博客梦?
1.现在的你是否还有梦想?
座在客厅的沙发上,戴着耳机,闭上眼睛,听着那首我听了上百遍的see you again,想着速度与激情的那群人,我很羡慕他们,一群志同道合的人在一起,干着一件大家都那么向往的事,梦想,感觉这两个字离我越来越远,太多世俗的东西,夺走了我们原有的天真,每天感觉除了上班,吃饭,睡觉,我感觉不到还有什么乐趣.
曾经也想自己写一些东西,可惜能力不够,一次偶然的机会,认识了敷衍不起,相见如故,一下子聊了很多,给我的印象是,大神级的人物,有想法,文艺青年,我谈到了我想搞一个自己博客的想法。
说到这里,他比我还激动,曾几何时,他也有这样的想法,那时候也是能力不够,现在终于有那么点能力了,说开始就开始,一开始的计划是,每个星期更新一个模块的东西,现在的情况是开源博客系统的基本原型都出来了,如果你心怀这样的一个博客梦想,想写一个真正属于自己的博客系统,那么还犹豫什么,加入我们。
在此给出see you again百度音乐盒地址:http://music.baidu.com/song/s/4707e5121d80855c1d51b在你不忙的时候,静下心来,听听音乐,音乐有的时候能带给我们一种微妙的感觉。
送大家一句话:梦想是春天的绿,娇嫩脆弱充满新意;梦想是生命的水,给人希望润物无声;梦想是天边的风,来去匆匆追之不及;梦想是凋零的叶,滋养大树迎来新生。
2.开源博客系列文章目录
《一步步搭建自己的博客》
一、一步步开发自己的博客 .NET版(1、页面布局、blog迁移、数据加载)
五、一步步开发自己的博客 .NET版(5、搜索功能)
六、一步步开发自己的博客 .NET版(6、手机端的兼容)
演示地址:http://blog.haojima.net/ 群内共享源码:469075305
3.开源博客框架说明
开发工具:vs2013+mssql+EF6.0
整个项目采用的Asp.net MVC4.0+EF6.0+经典的简单三层
项目采用最经典的三层架构,其实博客系统用这个完全就够用了,EF采用的是model frist,BLL层和DAL采用T4模板自动生成。下面是数据库表的一些说明。
4.在这个项目中你能学到什么?
博客系统的中的亮点,在这里使用HtmlAgilityPack组件解析HTML网页,我们只需要把我们的博客园的账号在这里输入就可以很快的把我们博客园中的文章备份过来。
其核心代码如下:
/// <summary> /// 根据用户导入cnblog数据 /// </summary> /// <param name="userName"></param> /// <returns></returns> public string Import(string userName, string iszf, string isshowhome, string isshowmyhome) { int blosNumber = 0; JavaScriptSerializer jss = new JavaScriptSerializer(); string url = "http://www.cnblogs.com/" + userName + @"/mvc/blog/sidecolumn.aspx"; HtmlAgilityPack.HtmlWeb htmlweb = new HtmlAgilityPack.HtmlWeb(); HtmlAgilityPack.HtmlDocument document = new HtmlDocument(); var docment = htmlweb.Load(url); string userid = GetCnblogUserId(userName); var liS = docment.DocumentNode.SelectNodes("//*[@id='sidebar_categories']/div[1]/ul/li"); foreach (var item in liS) { var tXPath = item.XPath; var href = item.SelectSingleNode(tXPath + "/a").Attributes["href"].Value; var blogtype = htmlweb.Load(href); //var entrylistItem = blogtype.DocumentNode.SelectNodes("//*[@id='mainContent']/div/div[2]/div[@class='entrylistItem']"); var entrylistItem = blogtype.DocumentNode.SelectNodes("//div[@class='entrylistItem']"); if (null == entrylistItem)//做兼容 entrylistItem = blogtype.DocumentNode.SelectNodes("//div[@class='post post-list-item']"); // if (null == entrylistItem) { continue; } foreach (var typeitem in entrylistItem) { var typeitemXPath = typeitem.XPath; var typeitemhrefObj = typeitem.SelectSingleNode(typeitemXPath + "/div/a"); if (null == typeitemhrefObj) //做兼容 typeitemhrefObj = typeitem.SelectSingleNode(typeitemXPath + "/h2/a"); var typeitemhref = typeitemhrefObj.Attributes["href"].Value; if (IsAreBlog(typeitemhref)) continue;//说明这篇文章已经备份过了的 var bloghtml = htmlweb.Load(typeitemhref); var blogcontextobj = bloghtml.DocumentNode.SelectSingleNode("//*[@id='cnblogs_post_body']");//.InnerHtml; if (blogcontextobj == null) continue;//有可能是加密文章 var blogcontext = blogcontextobj.InnerHtml; var blogNameObj = bloghtml.DocumentNode.SelectSingleNode("//*[@id='Header1_HeaderTitle']"); if (null == blogNameObj) blogNameObj = bloghtml.DocumentNode.SelectSingleNode("//*[@id='lnkBlogTitle']"); try { blogName = blogNameObj.InnerText; } catch (Exception) { } var blogtitle = bloghtml.DocumentNode.SelectSingleNode("//*[@id='cb_post_title_url']").InnerText; var blogurl = bloghtml.DocumentNode.SelectSingleNode("//*[@id='cb_post_title_url']").Attributes["href"].Value; var blogtypetagurl = "http://www.cnblogs.com/mvc/blog/CategoriesTags.aspx?blogApp=" + userName + "&blogId=" + userid + "&postId=" + typeitemhref.Substring(typeitemhref.LastIndexOf('/') + 1, typeitemhref.LastIndexOf('.') - typeitemhref.LastIndexOf('/') - 1); var blogtag = Blogs.Common.Helper.MyHtmlHelper.GetRequest(blogtypetagurl); var jsonobj = jss.Deserialize<Dictionary<string, string>>(blogtag); if (null == jsonobj) continue;//如果没有 则返回 (这里只能去 数字.html 不能取那种自定义的url) var tagSplit = jsonobj["Tags"].Split(','); var blogtagid = new List<int>(); for (int i = 0; i < tagSplit.Length; i++) { if (tagSplit[i].Length >= 1 && tagSplit[i].LastIndexOf('<') >= 1) { var blogtagname = tagSplit[i].Substring(tagSplit[i].IndexOf('>') + 1, tagSplit[i].LastIndexOf('<') - tagSplit[i].IndexOf('>') - 1); blogtagid.Add(this.GetTagId(blogtagname, userName)); } } var categoriesSplit = jsonobj["Categories"].Split(','); var blogtypeid = new List<int>(); for (int i = 0; i < categoriesSplit.Length; i++) { if (categoriesSplit[i].Length >= 1 && categoriesSplit[i].LastIndexOf('<') >= 1) { var blogtypename = categoriesSplit[i].Substring(categoriesSplit[i].IndexOf('>') + 1, categoriesSplit[i].LastIndexOf('<') - categoriesSplit[i].IndexOf('>') - 1); blogtypeid.Add(this.GetTypeId(blogtypename, userName)); } } var blogtimeobj = bloghtml.DocumentNode.SelectSingleNode("//*[@id='post-date']"); var blogtime = ""; if (null != blogtimeobj) blogtime = blogtimeobj.InnerText; DateTime? createtime = null; var Outcreatetime = DateTime.Now; if (DateTime.TryParse(blogtime, out Outcreatetime)) createtime = Outcreatetime; BlogsBLL blog = new BlogsBLL(); var myBlogTags = new BlogTagsBLL().GetList(t => blogtagid.Contains(t.Id), isAsNoTracking: false).ToList();//.ToList(); var myBlogTypes = new BLL.BlogTypesBLL().GetList(t => blogtypeid.Contains(t.Id), isAsNoTracking: false).ToList();//.ToList(); try { var modelMyBlogs = new ModelDB.Blogs() { BlogContent = blogcontext, BlogCreateTime = createtime, BlogTitle = blogtitle, BlogUrl = blogurl, IsDel = false, BlogTags = myBlogTags, BlogTypes = myBlogTypes, UsersId = GetUserId(userName), BlogForUrl = blogurl, IsForwarding = iszf == "true", IsShowMyHome = isshowmyhome == "true", IsShowHome = isshowhome == "true" }; blog.Add(modelMyBlogs); blog.save(); var newtag = string.Empty; modelMyBlogs.BlogTags.Where(t => true).ToList().ForEach(t => newtag += t.TagName + " "); var newblogurl = "/" + modelMyBlogs.BlogUsersSet.UserName + "/" + modelMyBlogs.Id + ".html"; SearchResult search = new SearchResult() { flag = modelMyBlogs.UsersId, id = modelMyBlogs.Id, title = blogtitle, clickQuantity = 0, blogTag = newtag, content = getText(blogcontext, document), url = newblogurl }; SafetyWriteHelper<SearchResult>.logWrite(search, PanGuLuceneHelper.instance.CreateIndex); var postid = blogurl.Substring(blogurl.LastIndexOf('/') + 1); postid = postid.Substring(0, postid.LastIndexOf('.')); testJumonyParser(modelMyBlogs.Id, 1, postid, userName); blosNumber++; } catch (Exception) { throw; } } } if (blosNumber > 0) { Blogs.BLL.Common.CacheData.GetAllTag(true); Blogs.BLL.Common.CacheData.GetAllType(true); Blogs.BLL.Common.CacheData.GetUserInfo(true); return "成功导入" + blosNumber + "篇Blog"; } return "ok"; }
private int GetTagId(string tagname, string userName) { BlogTagsBLL blogtag = new BlogTagsBLL(); try { var blogtagmode = blogtag.GetList(t => t.TagName == tagname); if (blogtagmode.Count() >= 1) return blogtagmode.FirstOrDefault().Id; else { blogtag.Add(new ModelDB.BlogTags() { TagName = tagname, IsDel = false, UsersId = GetUserId(userName) }); blogtag.save(); return GetTagId(tagname, userName); } } catch (Exception ex) { return -1; } }
private int GetTypeId(string typename, string userName) { BlogTypesBLL blogtype = new BlogTypesBLL(); var blogtagmode = blogtype.GetList(t => t.TypeName == typename); if (blogtagmode.Count() >= 1) return blogtagmode.FirstOrDefault().Id; else { blogtype.Add(new ModelDB.BlogTypes() { TypeName = typename, CreateTime = DateTime.Now, IsDel = false, UsersId = GetUserId(userName) }); blogtype.save(); return GetTypeId(typename, userName); } }
private int GetUserId(string userName) { BlogUsersBLL user = new BlogUsersBLL(); var blogtagmode = user.GetList(t => t.UserName == userName); if (blogtagmode.Count() >= 1) return blogtagmode.FirstOrDefault().Id; else { user.Add(new ModelDB.BlogUsersSet() { UserName = userName, IsDel = false, UserPass = "admin", UserNickname = string.IsNullOrEmpty(blogName.Trim()) ? userName : blogName, IsLock = false, UserMail = "无效", UserInfo = null }); try { user.save(false); } catch (Exception ex) { throw; } return GetUserId(userName); } }
private bool IsAreBlog(string url) { BLL.BlogsBLL blog = new BLL.BlogsBLL(); var blogs = blog.GetList(t => t.BlogUrl == url); return blogs.Count() >= 1; }
private string GetCnblogUserId(string url) { HtmlAgilityPack.HtmlWeb htmlweb = new HtmlAgilityPack.HtmlWeb(); var docment = htmlweb.Load("http://www.cnblogs.com/" + url); var list = docment.DocumentNode.SelectNodes("//link[@rel='stylesheet']"); foreach (var item in list) { if (null != item.Attributes && item.Attributes.Contains("href")) { var href = item.Attributes["href"].Value; href = href.Substring(href.LastIndexOf("/") + 1, href.IndexOf(".") - href.LastIndexOf("/") - 1); int userid = -1; if (int.TryParse(href, out userid)) return userid.ToString(); } } return ""; }
public string testJumonyParser(int BlogsId = 1, int BlogUsersId = 1, string postId = "4368417", string blogApp = "zhaopei") { bool isNext = true; int i = 0; //List<BlogCommentSet> blogcommen = new List<BlogCommentSet>(); BlogCommentBLL blogcommenbll = new BlogCommentBLL(); while (isNext) { i++; var url = "http://www.cnblogs.com/mvc/blog/GetComments.aspx?postId=" + postId + "&blogApp=" + blogApp + "&pageIndex=" + i; var jumony = new JumonyParser(); var htmlSource = jumony.LoadDocument(url).InnerHtml(); JavaScriptSerializer _jsSerializer = new JavaScriptSerializer(); CnBlogComments comm = _jsSerializer.Deserialize<CnBlogComments>(htmlSource); var commentsHtml = jumony.Parse(comm.commentsHtml); var pager = commentsHtml.Find("div.pager").FirstOrDefault(); if (null != pager) { var Next = pager.Find("*").LastOrDefault().InnerText(); if (Next != "Next >") isNext = false; } else isNext = false; var listComment = commentsHtml.Find("div.feedbackItem").ToList(); foreach (var item in listComment) { var commentDataNode = item.Find("div.feedbackListSubtitle span.comment_date").FirstOrDefault(); // var commentData = DateTime.Parse(commentDataNode.InnerText()); var commentUserNode = item.Find("div.feedbackListSubtitle a[target='_blank']").FirstOrDefault(); var commentUser = commentUserNode.InnerText(); var Content = item.Find("div.blog_comment_body").FirstOrDefault().InnerText(); blogcommenbll.Add( new BlogCommentSet() { BlogsId = BlogsId, CommentID = -1, IsDel = false, Content = Content, CreateTime = commentData, ReplyUserName = commentUser, BlogUsersId = BlogUsersId, IsInitial = true } ); } } try { blogcommenbll.save(false); } catch (Exception) { } return "ok"; }
在着比如说这个盘古分词,全文检索,效果如下
代码太多,我就截图算了...
当然开源博客系统中还有很多其他的东西,如果你感兴趣,或者你有什么好的主意,就加入我们的队伍中来吧。
5.机会来了,阿里云两年免费的主机!
虚拟空间申请地址:http://wanwang.aliyun.com/hosting/free/
虽说免费的东西都不怎么好,流量空间各方面都有限制,当时用来做个人博客已经够用了。。。
如果您对本篇文章感兴趣,那就麻烦您点个赞,您的鼓励将是我的动力。 当然您还可以加入QQ群:讨论。
如果您有更好的处理方式,希望不要吝啬赐教。