如何使用C#实现网易博客中圈子用户数据的采集

新浪博客,网易博客,都是博客中的佼佼者,其中网易提供的圈子信息,更胜一筹,使得一般用户能够通过访问圈子进入相关的群组,或者获取相关圈子用户的信息等,以实现各种精准营销的目的。虽然新浪遮遮掩掩不提供圈子的相关信息,相对而言,网易博客提供圈子,能够使得更多的人、更多的程序支持,推高博客的知名度及实用性。网易博客可以通过地址http://q.163.com/ 访问,它是经过两级分类的,如下所示。

 

 点击分类进入即可查看到每个子分类都有很多圈子,圈子累死QQ的群组,是某一兴趣团体的博客,里面收集很多相关的资料及信息,如下所示:

 

 这里不关心圈子的有哪些宝贵学习资料,我更关心的是这些圈子的用户如何采集出来,由于用户都是网易的用户,因此他们一个账户就会对应一个账号,有163.com,163.net,yeah.net,126.com等等的,我们先看看圈子的用户信息是如何显示的。

 

 我们看到上图里面圈子的信息是一个列表,有的圈子多,有的圈子少,不过他们的名称中都会关联一个博客地址的,由于博客地址和邮件地址有一一对应关系,因此可以获取对应的邮件信息,这就是我们所要的重要信息。

下面用一个程序来介绍如何采集圈子的分类、圈子数据以及圈子用户资料信息,测试的程序如下所示:

 

 下面我们来看看按钮”刷新分类数据“的实现代码,主要是获取圈子大类、圈子子类以及保存数据操作,代码如下所示:

        private void btnRefreshCategory_Click(object sender, EventArgs e)
        {
            string url = "http://q.163.com/";
            string mainTypeReg = "<div\\s*style=\"font-size:14px;\"><b><a\\s*?href=\"(?<value>.*?)\">(?<key>.*?)</a></b></div>";
            string subTypeReg = "<div\\s*class=\"left\"><a\\s*href=\"(?<value>.*?)\">(?<key>.*?)</a></div> ";

            #region 取得大类

            httpHelper.Encoding = Encoding.Default;
            string content = httpHelper.GetHtml(url);
            Regex re = new Regex(mainTypeReg, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
            Match mc = re.Match(content);
            Dictionary<string, string> typeDict = new Dictionary<string, string>();
            if (mc.Success)
            {
                MatchCollection mcs = re.Matches(content);
                foreach (Match me in mcs)
                {
                    string strKey = me.Groups["key"].Value;
                    string strValue = me.Groups["value"].Value;
                    //截取连接前面部分作为大类标识
                    string newValue = strValue.TrimEnd('/');
                    int eIndex = newValue.LastIndexOf('/');
                    newValue = newValue.Substring(0, eIndex) + "/";

                    if (!typeDict.ContainsKey(strKey))
                    {
                        typeDict.Add(strKey, newValue);
                    }
                }
            }
            #endregion

            #region 取得子类
            Dictionary<string, CircleSubTypeInfo> circleDict = new Dictionary<string, CircleSubTypeInfo>();
            re = new Regex(subTypeReg, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
            mc = re.Match(content);
            if (mc.Success)
            {
                MatchCollection mcs = re.Matches(content);
                foreach (Match me in mcs)
                {
                    string strKey = me.Groups["key"].Value;
                    string strValue = me.Groups["value"].Value;
                    //截取连接前面部分作为大类标识
                    string typeValue = strValue.TrimEnd('/');
                    int eIndex = typeValue.LastIndexOf('/');
                    typeValue = typeValue.Substring(0, eIndex) + "/";

                    if (!circleDict.ContainsKey(strKey))
                    {
                        CircleSubTypeInfo info = new CircleSubTypeInfo();
                        info.Name = strKey;
                        info.LinkUrl = strValue;
                        info.TypeUrlValue = typeValue;

                        circleDict.Add(strKey, info);
                    }
                }
            }
            #endregion

            #region 保存数据
            Database db = DatabaseFactory.CreateDatabase();
            DbCommand command = null;
            string sql = "";

            foreach (string key in typeDict.Keys)
            {
                sql = string.Format("Insert into CircleType(TypeName, TypeValue) values('{0}', '{1}') ", key, typeDict[key]);   
                command = db.GetSqlStringCommand(sql);
                db.ExecuteNonQuery(command);
            }

            foreach (string key in circleDict.Keys)
            {
                CircleSubTypeInfo info = circleDict[key];
                sql = string.Format("Insert into CircleSubType(SubTypeName, LinkUrl, TypeUrlValue) values('{0}', '{1}', '{2}') ", info.Name, info.LinkUrl, info.TypeUrlValue);
                command = db.GetSqlStringCommand(sql);
                db.ExecuteNonQuery(command);
            } 
            #endregion

            this.lblTips.Text = "获取分类操作完成";

        }   

其中主要是采用了正则表达式来对获取的内容进行处理,然后整理出来相关的分类数据放到数据库中,以便获取圈子用户信息作准备。

有了圈子分类信息,我们第二步骤就是看如何获取圈子数据,然后才能通过圈子的唯一ID获取圈子的用户资料,这步也是必须的,获取圈子资料是比较复杂的,需要组装较多的参数获取资料,部分代码如下所示。

            foreach (string key in urlDict.Keys)
            {
                string keyNumberReg = "/mapCircleList/(?<d1>[1-9]\\d*)/(?<d2>[1-9]\\d*)*/(?<d3>[1-9]\\d*)/";
                Regex re = new Regex(keyNumberReg, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
                
                LogTextHelper.WriteLine(string.Format("正在处理类型:{0}", urlDict[key]));
                cookie = new System.Net.CookieContainer();

                string urlKey = key;
                Match mc = re.Match(urlKey);
                string d1 = mc.Groups["d1"].Value;
                string d2 = mc.Groups["d2"].Value;
                string d3 = mc.Groups["d3"].Value;
                int pageSize = 30;

                urlKey = urlKey.Trim('/');//清除前后的/字符
                string url = "http://q.163.com/dwr/call/plaincall/CircleMainpageBean.getCircleByType2IdInMemberOrder.dwr";
                //string refUrl = "http://q.163.com/mapCircleList/2/11/48/?fromCircleCircleMap";
                string refUrl = string.Format("http://q.163.com/{0}/?fromCircleCircleMap", urlKey);
                #region 内容正则表达式
                StringBuilder circleReg = new StringBuilder();
                circleReg.Append("s[0-9]\\d*.circleId=(?<circleId>[0-9]\\d*[^;])");
                circleReg.Append(".*?s[0-9]\\d*.circleType1Str=\"(?<circleType1Str>.*?)\"");
                circleReg.Append(".*?s[0-9]\\d*.circleType2Str=\"(?<circleType2Str>.*?)\"");
                circleReg.Append(".*?s[0-9]\\d*.createDateStr=\"(?<createDateStr>.*?)\"");
                circleReg.Append(".*?s[0-9]\\d*.creatorId=(?<creatorId>[0-9]\\d*[^;])");
                circleReg.Append(".*?s[0-9]\\d*.creatorName=\"(?<creatorName>.*?)\"");
                circleReg.Append(".*?s[0-9]\\d*.creatorSpaceUrl=\"(?<creatorSpaceUrl>.*?)\"");
                circleReg.Append(".*?s[0-9]\\d*.description=\"(?<description>.*?)\"");
                circleReg.Append(".*?s[0-9]\\d*.joinDeclaration=\"(?<joinDeclaration>.*?)\"");
                circleReg.Append(".*?s[0-9]\\d*.linkImgUrl=\"(?<linkImgUrl>.*?)\"");
                circleReg.Append(".*?s[0-9]\\d*.memberNum=(?<memberNum>[0-9]\\d*[^;])");
                circleReg.Append(".*?s[0-9]\\d*.name=\"(?<name>.*?)\"");
                circleReg.Append(".*?s[0-9]\\d*.urlName=\"(?<urlName>.*?)\""); 
                circleReg.Append( ".*?s[0-9]\\d*.visitNum=(?<visitNum>[0-9]\\d*[^;])")

通过组装参数数据,然后获取页面数据,对页面数据进行分析即可,主要代码如下所示:

                    if (mc.Success)
                    {
                        string message = string.Format("正在处理类型{0}:{1}, 第{2}次数据, 共处理了{3}", urlDict[key], url, i + 1, j);
                        CallCtrlWithThreadSafety.SetText(this.lblTips, message, this);
                        Application.DoEvents();
                        Thread.Sleep(10);

                        MatchCollection mcs = re.Matches(content);
                        foreach (Match me in mcs)
                        {
                            #region MyRegion
                            j++;

                            int memberNum = 0;
                            try
                            {
                                memberNum = Convert.ToInt32(me.Groups["memberNum"].Value);
                            }
                            catch { }
                            if (memberNum < 50)
                            {
                                flag = false;
                                break; 
                            }
            
                            sql = string.Format(@"insert into Circle(circleId,circleType1Str,circleType2Str,createDateStr,creatorId,
                            creatorName,creatorSpaceUrl,description,joinDeclaration,linkImgUrl,memberNum,name2,urlName,SubTypeName) 
                            values('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}','{9}','{10}','{11}','{12}','{13}') ", me.Groups["circleId"].Value,
                            UnicodeHelper.UnicodeToString(me.Groups["circleType1Str"].Value.Replace("'", "")), UnicodeHelper.UnicodeToString(me.Groups["circleType2Str"].Value.Replace("'", "")),
                            me.Groups["createDateStr"].Value, me.Groups["creatorId"].Value, UnicodeHelper.UnicodeToString(me.Groups["creatorName"].Value),
                            me.Groups["creatorSpaceUrl"].Value, UnicodeHelper.UnicodeToString(me.Groups["description"].Value.Replace("'", "")), UnicodeHelper.UnicodeToString(me.Groups["joinDeclaration"].Value.Replace("'", "")),
                            me.Groups["linkImgUrl"].Value, me.Groups["memberNum"].Value, UnicodeHelper.UnicodeToString(me.Groups["name"].Value.Replace("'", "")), me.Groups["urlName"].Value, urlDict[key]);
                            command = db.GetSqlStringCommand(sql);
                            try
                            {
                                db.ExecuteNonQuery(command);
                            }
                            catch (Exception ex)
                            {
                                LogTextHelper.WriteLine(sql);
                                LogTextHelper.WriteLine(ex.ToString());
                            }

                            message = string.Format("正在处理{0}:{1} 正在写入数据{2}次", urlDict[key], url, j);
                            CallCtrlWithThreadSafety.SetText(this.lblTips, message, this);
                            Application.DoEvents();
                            Thread.Sleep(10);
                            
                            #endregion
                        }                            
                    }
                    else
                    {
                        flag = false;//没有匹配就停止  
                        break;
                    }

                } 

 构造获取圈子用户信息也是比较复杂的一个过程,需要组装更多的参数来获取相关的数据,部分主要实现代码如下所示:

            httpHelper = new HttpHelper();
            httpHelper.Encoding = Encoding.Default;
            cookie = new CookieContainer();
            Regex re = null;
            Match mc = null;
            int pageSize = 30;
            string url = "http://q.163.com/dwr/call/plaincall/CircleBean.getNewCircleUsers.dwr";

            foreach (string key in circlelDict.Keys)
            {
                string circleId = key;
                string urlName = circlelDict[key];
                string refUrl = string.Format("http://q.163.com/{0}/members/", urlName);

                #region 内容正则表达式
                StringBuilder circleReg = new StringBuilder();
                circleReg.Append("s[0-9]\\d*.ageStr=\"(?<ageStr>.*?)\"");
                circleReg.Append(".*?s[0-9]\\d*.city=\"(?<city>.*?[^;])\"");
                circleReg.Append(".*?s[0-9]\\d*.hometownCity=(\"(?<hometownCity>.*?[^;])\"|(?<hometownCity>null))");
                circleReg.Append(".*?s[0-9]\\d*.hometownProvince=(\"(?<hometownProvince>.*?)\"|(?<hometownProvince>null))");
                circleReg.Append(".*?s[0-9]\\d*.name=(\"(?<name>.*?)\"|(?<name>null))");
                circleReg.Append(".*?s[0-9]\\d*.nickname=(\"(?<nickname>.*?)\"|(?<nickname>null))");
                circleReg.Append(".*?s[0-9]\\d*.profileImage140=\"(?<profileImage140>.*?)\"");
                circleReg.Append(".*?s[0-9]\\d*.profileImage60=\"(?<profileImage60>.*?)\"");
                circleReg.Append(".*?s[0-9]\\d*.province=\"(?<province>.*?)\"");
                circleReg.Append(".*?s[0-9]\\d*.qq=(\"(?<qq>.*?)\"|(?<qq>null))");
                circleReg.Append(".*?s[0-9]\\d*.realName=(\"(?<realName>.*?)\"|(?<realName>null))");
                circleReg.Append(".*?s[0-9]\\d*.spaceName=(\"(?<spaceName>.*?)\"|(?<spaceName>null))");
                circleReg.Append(".*?s[0-9]\\d*.userId=(?<userId>[0-9]\\d*[^;])");
                circleReg.Append(".*?s[0-9]\\d*.userName=\"(?<userName>.*?)\"");
                #endregion

                bool flag = true;
                int i = 0;
                int j = 0;
                List<CircleMemberInfo> entityList = new List<CircleMemberInfo>();
                while (flag)
                {
                    #region 构造提交参数
                    StringBuilder sb = new StringBuilder();
                    sb.AppendFormat("callCount=1");
                    sb.AppendFormat("&page=/{0}/members/", urlName);
                    sb.AppendFormat("&httpSessionId=");
                    sb.AppendFormat("&scriptSessionId=D4DAC4AD9C3BF9B71C82802BDDBA0C25369");
                    sb.AppendFormat("&c0-scriptName=CircleBean");
                    sb.AppendFormat("&c0-methodName=getNewCircleUsers");
                    sb.AppendFormat("&c0-id=0");//保留字符
                    sb.AppendFormat("&c0-param0=number:{0}", circleId);//11
                    sb.AppendFormat("&c0-param1=number:{0}", pageSize);//数量
                    sb.AppendFormat("&c0-param2=number:{0}", pageSize * i);//0,30,60
                    sb.AppendFormat("&c0-param3=boolean:true");
                    sb.AppendFormat("&batchId={0}", i);

                    i++;  

                    #endregion 

然后我们通过代码来获取页面数据了,实现代码如下:

string content = "";
                    try
                    {
                        httpHelper.ContentType = "text/plain";
                        content = httpHelper.GetHtml(url, cookie, sb.ToString(), true, refUrl);
                        re = new Regex(circleReg.ToString(), RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
                        mc = re.Match(content);
                    }
                    catch (Exception ex)
                    {
                        LogTextHelper.WriteLine(ex.ToString());
                        break;

                    } 

然后我们就开始用正则表达式来分析返回的数据,以便显示或者添加到数据库中,以供他用,代码实现如下所示:、

                        MatchCollection mcs = re.Matches(content);
                        foreach (Match me in mcs)
                        {
                            #region MyRegion
                            j++;                           

                            sql = string.Format(@"insert into CircleMember(userId,userName,realName,nickname,circleId) 
                            values('{0}','{1}','{2}','{3}','{4}') ", me.Groups["userId"].Value, httpHelper.RemoveHtml(UnicodeHelper.UnicodeToString(me.Groups["userName"].Value)),
                             httpHelper.RemoveHtml(UnicodeHelper.UnicodeToString(me.Groups["realName"].Value.Replace("'", ""))), httpHelper.RemoveHtml(UnicodeHelper.UnicodeToString(me.Groups["nickname"].Value.Replace("'", ""))), circleId);
                            command = db.GetSqlStringCommand(sql);
                            try
                            {
                                db.ExecuteNonQuery(command);
                            }
                            catch (Exception ex)
                            {
                                LogTextHelper.WriteLine(sql);
                                LogTextHelper.WriteLine(ex.ToString());
                            }

                            message = string.Format("正在处理{0} 正在写入数据{1}次", urlName, j);
                            CallCtrlWithThreadSafety.SetText(this.lblTips, message, this);
                            Application.DoEvents();
                            Thread.Sleep(10); 
                            #endregion

                         }

以上就是获取数据的一个完整的过程,其中涉及到获取圈子大类、圈子分类、圈子信息,以及最终获取圈子的用户信息,其中较为详细的介绍了各种数据的正则分析过程,如果您有这方面的应用,一个可以参考下面的代码,第二个也可以参考我的软件《易博搜搜》,其中就涉及到了网易博客圈子的邮件采集,如下所示。

 


该软件除了可以采集网易博客圈子用户的邮件信息,给营销推广人提供资料外,还可以利用网易博客的找朋友模块,获取相关的用户数据信息,当然也是可以转换为邮件地址信息的了,如下所示。

 

以上对网易博客的应用的代码实现以及一个较为综合的软件产品介绍,希望能带给大家更多的启示和知识了解。 

本文转自博客园伍华聪的博客,原文链接:如何使用C#实现网易博客中圈子用户数据的采集,如需转载请自行联系原博主。

时间: 2024-10-22 09:15:39

如何使用C#实现网易博客中圈子用户数据的采集的相关文章

无社交不博客 网易博客社交化升级融入SNS

中介交易 SEO诊断 淘宝客 云主机 技术大厅 SNS(Social Network Service-社会化网络)网站的异军突起,让稍显得有点沉闷的互联网出现了新躁动.网友把注意力转向SNS网站,这一度让专业博客网以及门户博客频道感受到了莫大的威胁.曾有人分析,SNS网站会分流博客的流量,将导致个人博客的活跃度和影响力出现下滑态势. 现实却并未真正向着推测的方向发展,中国博客的活跃度反而有所提高.2009年初CNNIC发布的互联网发展报告显示,半年内更新过博客的比重较2007年底提高了11.7%

分析网易博客广告推广计划网赚的可行性

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 博客广告共享计划自实施以来,很多网友在百度知道上都在咨询这个事情.问:网易博客共享计划是真的吗?网易博客共享计划是骗人的吗?怎样才能参与到网易博客共享计划中?我的网易博客共享计划中账号怎么一直没有收入?怎么才能提高网易博客共享计划账户收入等各类问题. 一,怎样才能收到网易博客广告共享计划邀请: 博客广告共享计划帮助内容里一句话:网易博客会定期

超级链接在博客中的作用

对于一个博客来说,我们建议博客的内容尽量是原创的,不过我们提倡原创的同时,并不反对转帖,关键是如何全方位尊重原创,并合理转载. 转载要求不能侵权他人版权,任何情况下都不应该转载有版权的文章.对于没有注明版权的文章,转载的时候也应该尊重原创,并按要求转帖. 转载的要求,首要是应该注明正确的来源. 我们看到一篇文章可能来自某个论坛,但是经过分析这篇文章也是这个论坛转载的,那么我觉得,我不应该注明文章来源于这个论坛,因为这显得不公平.这种情况应该进行考证,通过Google和Baidu搜索引擎来确认文章

从千万级访问量的博客中得到的启示

做网络推广的朋友很多都有门户网站的博客,少的又几个,多的有有成百上千个.不过大多数朋友都是将门户网站的博客当成是外链的基地,群发大量的信息或者发布一些乱七八糟的文章来发布外链,博客的作用似乎就只是用来发布外链的.但是我们看一下下面一张图,你就会觉得门户网站的博客的作用远非于此.   这是一个做生活常识类的博客,它的累计访问量已经突破了一千一百万,关注人气达到七千多,而且几乎每一篇网站都有转载,所以实际算起来每篇文章的阅读量远高于此,如果我们在这个博客的每篇文章上面加上我们的网站链接的话,那效果你

博客中添加日历的php代码

想不想在你得博客中添加日历啊?blue1000在这里跟大家简洁的分享一款PHP中博客日历实现代码,有需要的朋友参考一下,里面有一句是查询数据库的这个很简单,你只要修改一下字段名与你数据库相同就行了. 代码如下: function calendarnew($starttime = 0) { global $db, $tablepre, $timestamp, $site_timeoffset, $site_dateformat, $curtime; $starttime = $starttime

github-请问Jekyll博客中如何用相对路径来加载图片

问题描述 请问Jekyll博客中如何用相对路径来加载图片 请教关于Jekyll博客写的markdown文件,博文中怎么插入图片? 在_post下再键一个目录用来放置对应博文的图片,md中用相对目录表示,可是实际才显示不出来 又不想用绝对路径,请问该如何解决 万分感谢----

网易博客个性化留下的问题

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 网易博客和新浪博客是我用得时间最长的,得出两个结论,网易blog是用来玩的,新浪blog是用来写的. 如果你用心一点,就会发觉网易的用户90%是90后或者80后,而新浪的用户则是80后,70后甚至是60后.如果你更用心一点,你会发觉一些年轻人,什么潮,in,非主流主题类型的论坛,很多会员签名都不约而同写上自己的163blog,而不是新浪blo

如何在wordpress博客中添加炫酷的加载中动画特效

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 一个优秀的博客不仅仅要给读者得到想要的知识或内容,也应该给予读者阅读时的享受.因为有些朋友的网速很慢,而博客中的图片等内容挺多的,所以在网页打开时往往需要等半天,如果此时能够显示一个漂亮的入场动画,也许可以缓解等待网页打开的无奈感.今天就来分享一下周叔博客的加载动画特效. 特效的实现并不麻烦,简单来说就是用几个层来遮罩页面,然后在这个层之上添

博客中国是疯了?还是真的离成功不远了?

最近半年,博客中国变化之快远远超出来我们的想象.于是,张静君在自己的主页中只能无奈的叹息:救救方兴东博士,中国的网络不应该这样! 洪波也常在他的blog中对博客中国目前的一些做法嗤之以鼻:圈内人士重新转移阵地回到DONEWS 里面继续混IT江湖,大家都有一种感觉:博客中国疯了!世界上许多NB的成功人士都说,当别人都把你当做疯子 来看待的时候,你就离成功不远了. 但是,博客中国真的离成功不远了么? 王通今儿和大家一块来研究研究.博客中国为什么能够火起来?早期,博客中国网站是怎么火起来的?我觉得靠的