在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
一,分析 1,群数据获取 当访问http://qun.qq.com/air/#mygroup我们通过Fiddler可以查看到QQ群列表是从http://qun.qq.com/air/group/mine?w=a这个URL获取到的群列表信息 其中返回的json数据,json构成如下 从上面我们可以看出c包含的是群列表信息,r包含的是服务器的信息,其中c的某一项构成如下图所示
从上面可以看出项名称就是群号,owner为所有者,name为群名称,memo群描述,brief为群公告信息,还有其他的一些信息,大家自己去匹配,我这里就不一一解释了. 2, 单个群的成员获取,在上面我们分析了如何获取群列表,下面我们将分析如何取得单个群成员的数据 const string groupMemberUrl = "http://qun.qq.com/air/{0}/addr/index/type/1/p/{1}?w=n&_={2}";
string memberURL = string.Format(groupMemberUrl, gInfo.Number, page, JavascriptAction.Random());
我们按照这样的地址去请求,就会得到QQ群成员的HTML,然后我在解析HTML就可以得到相应的数据了 二,实现 1, 获取群列表 public List<GroupInfo> GetGroupInfos()
{ if (!isLogin) Login();
List<GroupInfo> giList = new List<GroupInfo>();
string json = GetWebData<string>(string.Format(groupListUrl, JavascriptAction.Random()));
try
{ var jsonObj = JavaScriptEngine.Run("var m=" + json + ";m.c") as Dictionary<string, object>;
foreach (var key in jsonObj.Keys)
{ var gi = (jsonObj[key] as Dictionary<string, object>);
if (!gi.ContainsKey("owner")) continue;
string owner = gi["owner"].ToString();
string name = gi["name"].ToString();
string max_member = gi["max_member"].ToString();
string create_time = gi["create_time"].ToString();
string notice = gi["brief"].ToString();
string number = key;
string memo = gi["memo"].ToString();
giList.Add(new GroupInfo()
{ CreateTime = JavascriptAction.GetTimeByJsTime(Convert.ToInt64(create_time)), MaxNumber = Convert.ToInt32(max_member), Memo = memo, Name = name, Notice = notice, Number = number, Owner = owner }); } } catch { }
return giList;
} 上面的函数实现了群列表的获取,需要说明的是获取到的json是同过javascript引擎来运行的,javascript运行我通过Javascript .NET(http://javascriptdotnet.codeplex.com/releases/view/52449)来实现的,获取web数据参考我的blog的另外的文章,文章有实现源代码,至于登陆我最后会说明 2, 获取群成员 public List<QQGroupMemberInfo> GetMemberInfo(GroupInfo gInfo)
{ if (!isLogin) Login();
List<QQGroupMemberInfo> gmis = new List<QQGroupMemberInfo>();
int page = 1;
int pageCount = 0;
GETMEMBER: string memberURL = string.Format(groupMemberUrl, gInfo.Number, page, JavascriptAction.Random());
string html = GetWebData<string>(memberURL);
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html); if (pageCount < 1)
{ var seeBtn = doc.DocumentNode.SelectSingleNode(pageBtnPath); pageCount = Convert.ToInt32(seeBtn.Attributes["allpage"].Value);
} var trs = doc.DocumentNode.SelectNodes(memberTrPath); foreach (var tr in trs)
{ var tds = tr.Descendants("td").ToList();
if (tds.Count < 1) continue;
string groupNick = tds[1].Element("a").InnerText.Trim();
string qq = tds[2].Element("span").InnerText.Trim();
gmis.Add(new QQGroupMemberInfo()
{ NickName = groupNick, QQ = qq }); } if (page < pageCount)
{ page++; goto GETMEMBER;
} return gmis;
} 上面的函数实现了群成员的获取,其中HTML的解析式通过HtmlAgilityPack(http://htmlagilitypack.codeplex.com/)来实现,HtmlAgilityPack通过XPATH语法去解析实现的,关于xpath不是很难,大家查查资料就会了 public class LoginQQ : WebPageAction, ILogin, IValidateCodeAction
{ static JavaScriptEngine _javaEngine = new JavaScriptEngine();
static bool _isInitJava = false;
Random _r = new Random();
const string loginFormUrl = "http://ui.ptlogin2.qq.com/cgi-bin/login?link_target=blank&appid=15000101&hide_title_bar=1&s_url=http%3A%2F%2Fim.qq.com%2Floginproxy.html%3Flogin_level%3D2&f_url=loginerroralert&target=self";
private User User { get; set; }
string _qq = "";
public LoginQQ(CookieManager cookieManager, User user)
: base(user.UserName)
{ _cookieManager = cookieManager; User = user; _qq = user.UserName.Split('@')[0];
if (!_isInitJava)
{ _javaEngine.Run(System.IO.File.ReadAllText(@"JavaScript\qq\md5_3.js"));
_isInitJava = true;
} } public override JavaScriptEngine JavaScriptEngine
{ get { return _javaEngine;
} set { _javaEngine = value;
} } string vc_type = "";
public bool Login(string referer)
{ DateTime beginTime = DateTime.Now; string html = "";
html = GetWebData<string>(loginFormUrl);
if (!regForm.IsMatch(html))
ThrowException(507, html); var form = GetFormDataByFormHtml(regForm.Match(html).Value); string url = "http://ptlogin2.qq.com/check?uin=" + _qq + "&appid=15000101&" + JavascriptAction.Random();
html = GetWebData<string>(url, referer: loginFormUrl);
string vcode = "";
if (html.Contains("ptui_checkVC('1','"))
{ vc_type = html.Replace("ptui_checkVC('1','", "").Replace("'", "").Replace(")", "").Replace(";", "");
form = new NameValueCollection();
if (!ValidationImageCode(form, loginFormUrl)) { return false; };
vcode = form["verifycode"];
} else if (html.Contains("ptui_checkVC('0','"))
{ vcode = html.Replace("ptui_checkVC('0','", "").Replace("'", "").Replace(")", "").Replace(";", "");
} TimeSpan _tspan = TimeSpan.FromTicks(DateTime.Now.Ticks - beginTime.Ticks); if (_tspan.Seconds < 20)
Thread.Sleep(TimeSpan.FromSeconds(_r.Next(20 - _tspan.Seconds, 30))); string pMd5 = GetPwdString(User.Pwd, vcode);
string action = "0-0" + "-" + (JavascriptAction.GetTime(DateTime.Now) - JavascriptAction.GetTime(beginTime));
url = "http://ptlogin2.qq.com/login?u=" + _qq + "&p=" + pMd5 + "&verifycode=" + vcode + "&aid=15000101&u1=http%3A%2F%2Fim.qq.com%2Floginproxy.html%3Flogin_level%3D2&h=1&ptredirect=0&ptlang=2052&from_ui=1&dumy=&fp=loginerroralert&action=" + action + "&mibao_css=";
html = GetWebData<string>(url, referer: loginFormUrl);
if (html.Contains("登录成功"))
{ return true;
} return false;
} private string GetPwdString(string pwd, string vcode)
{ string script = "md5(md5_3('" + pwd + "') + '" + vcode + "')";
return JavaScriptEngine.Run(script).ToString();
} public bool ValidateLogin(string referer)
{ var cks = _cookieManager.GetCookies(new Uri(referer).Host);
if (cks["uin"] != null && cks["skey"] != null)
{ return true;
} return false;
} public bool ValidationCode(string code, string referer)
{ return true;
} public Image GetValidateCode(string referer)
{ string url = "http://captcha.qq.com/getimage?aid=15000101&r=" + JavascriptAction.Random() + "&uin=" + _qq + "&vc_type=" + vc_type;
return GetWebData<Image>(url, referer: referer);
} public bool ValidationImageCode(NameValueCollection customFormItems, string referer)
{ ValidateReturn code = null;
do
{ Image image = GetValidateCode(referer); code = this.FireValidateCode(image);
if (code.IsCancel)
{ return false;
} if (customFormItems.AllKeys.Contains("verifycode"))
{ customFormItems.Remove("verifycode");
} customFormItems.Add("verifycode", code.Code);
} while (code.IsChange || !ValidationCode(code.Code, referer));
return true;
} } 第二种就是从客户端点击,如QQ空间按钮,客户端会调用浏览器跳转 http://ptlogin2.qq.com/jump?ptlang=2052&clientuin=442799037&clientkey=687E58BB1B99061A S62F0C751CF1763F1A8EEA3E8F2AF52B7956193D947F78B6&u1=http%3A%2F%2Fuser.qzone.qq.com%2F442799037%2Finfocenter&ADUIN=442799037&ADSESSION=1335488190&ADTAG=CLIENT.QQ.3187_Mysrv.0这样的地址,通过这个URL实现登陆,那么我们只需要HOOK ShellExecuteExW这个入口点就可以实现URL的截取,关于钩子如何实现,我前面有文章已说过,同样贴上代码供大家参考 public class ClientQQWebction : WebPageAction, IDisposable
{ const string loginUrl = "http://ptlogin2.qq.com/jump?ptlang={2}&clientuin={0}&clientkey={1}&u1={3}";
const string getEmail = "http://accountadm.qq.com/cgi-bin/account/ajaxgetmail?uin={0}";
const string groupListUrl = "http://qun.qq.com/air/group/mine?w=a&_={0}";
const string groupMemberUrl = "http://qun.qq.com/air/{0}/addr/index/type/1/p/{1}?w=n&_={2}";
const string pageBtnPath = "//input[@type=\"button\" and @value=\"查看\" and @act=\"gotopage\"]";
const string memberTrPath = "//table[@class=\"addressList\"]/tr";
CleintKeyInfo _cleintKeyInfo = null;
bool isLogin = false;
public ClientQQWebction(CleintKeyInfo cki)
{ _cleintKeyInfo = cki; } private void Login()
{ string loginURL = string.Format(loginUrl, _cleintKeyInfo.ClientUin, _cleintKeyInfo.ClientKey, _cleintKeyInfo.PtLang, string.Format(getEmail, _cleintKeyInfo.ClientUin));
var loca = GetWebData<ResponseLocation>(loginURL); if (_cookieManager.GetCookies("qq.com")["skey"] != null)
{ isLogin = true;
return;
} throw new Exception("登陆失败");
} public string GetEmail()
{ if (!isLogin) Login();
string emailUrl = String.Format(getEmail, _cleintKeyInfo.ClientUin);
var html = GetWebData<string>(emailUrl);
if (regEmail.IsMatch(html))
return regEmail.Match(html).ToString();
else
return null;
} public List<GroupInfo> GetGroupInfos()
{ if (!isLogin) Login();
List<GroupInfo> giList = new List<GroupInfo>();
string json = GetWebData<string>(string.Format(groupListUrl, JavascriptAction.Random()));
try
{ var jsonObj = JavaScriptEngine.Run("var m=" + json + ";m.c") as Dictionary<string, object>;
foreach (var key in jsonObj.Keys)
{ var gi = (jsonObj[key] as Dictionary<string, object>);
if (!gi.ContainsKey("owner")) continue;
string owner = gi["owner"].ToString();
string name = gi["name"].ToString();
string max_member = gi["max_member"].ToString();
string create_time = gi["create_time"].ToString();
string notice = gi["brief"].ToString();
string number = key;
string memo = gi["memo"].ToString();
giList.Add(new GroupInfo()
{ CreateTime = JavascriptAction.GetTimeByJsTime(Convert.ToInt64(create_time)), MaxNumber = Convert.ToInt32(max_member), Memo = memo, Name = name, Notice = notice, Number = number, Owner = owner }); } } catch { }
return giList;
} public List<QQGroupMemberInfo> GetMemberInfo(GroupInfo gInfo)
{ if (!isLogin) Login();
List<QQGroupMemberInfo> gmis = new List<QQGroupMemberInfo>();
int page = 1;
int pageCount = 0;
GETMEMBER: string memberURL = string.Format(groupMemberUrl, gInfo.Number, page, JavascriptAction.Random());
string html = GetWebData<string>(memberURL);
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html); if (pageCount < 1)
{ var seeBtn = doc.DocumentNode.SelectSingleNode(pageBtnPath); pageCount = Convert.ToInt32(seeBtn.Attributes["allpage"].Value);
} var trs = doc.DocumentNode.SelectNodes(memberTrPath); foreach (var tr in trs)
{ var tds = tr.Descendants("td").ToList();
if (tds.Count < 1) continue;
string groupNick = tds[1].Element("a").InnerText.Trim();
string qq = tds[2].Element("span").InnerText.Trim();
gmis.Add(new QQGroupMemberInfo()
{ NickName = groupNick, QQ = qq }); } if (page < pageCount)
{ page++; goto GETMEMBER;
} return gmis;
} public void Dispose()
{ _cookieManager = null;
JavaScriptEngine = null;
} } OK,到此完成,下篇实现qq好友数据获取 最近失业了,求职中………
转载请注明:http://www.cnblogs.com/Rolends
一,分析 1,群数据获取 当访问http://qun.qq.com/air/#mygroup我们通过Fiddler可以查看到QQ群列表是从http://qun.qq.com/air/group/mine?w=a这个URL获取到的群列表信息 其中返回的json数据,json构成如下 从上面我们可以看出c包含的是群列表信息,r包含的是服务器的信息,其中c的某一项构成如下图所示
从上面可以看出项名称就是群号,owner为所有者,name为群名称,memo群描述,brief为群公告信息,还有其他的一些信息,大家自己去匹配,我这里就不一一解释了. 2, 单个群的成员获取,在上面我们分析了如何获取群列表,下面我们将分析如何取得单个群成员的数据 const string groupMemberUrl = "http://qun.qq.com/air/{0}/addr/index/type/1/p/{1}?w=n&_={2}";
string memberURL = string.Format(groupMemberUrl, gInfo.Number, page, JavascriptAction.Random());
我们按照这样的地址去请求,就会得到QQ群成员的HTML,然后我在解析HTML就可以得到相应的数据了 二,实现 1, 获取群列表 public List<GroupInfo> GetGroupInfos()
{ if (!isLogin) Login();
List<GroupInfo> giList = new List<GroupInfo>();
string json = GetWebData<string>(string.Format(groupListUrl, JavascriptAction.Random()));
try
{ var jsonObj = JavaScriptEngine.Run("var m=" + json + ";m.c") as Dictionary<string, object>;
foreach (var key in jsonObj.Keys)
{ var gi = (jsonObj[key] as Dictionary<string, object>);
if (!gi.ContainsKey("owner")) continue;
string owner = gi["owner"].ToString();
string name = gi["name"].ToString();
string max_member = gi["max_member"].ToString();
string create_time = gi["create_time"].ToString();
string notice = gi["brief"].ToString();
string number = key;
string memo = gi["memo"].ToString();
giList.Add(new GroupInfo()
{ CreateTime = JavascriptAction.GetTimeByJsTime(Convert.ToInt64(create_time)), MaxNumber = Convert.ToInt32(max_member), Memo = memo, Name = name, Notice = notice, Number = number, Owner = owner }); } } catch { }
return giList;
} 上面的函数实现了群列表的获取,需要说明的是获取到的json是同过javascript引擎来运行的,javascript运行我通过Javascript .NET(http://javascriptdotnet.codeplex.com/releases/view/52449)来实现的,获取web数据参考我的blog的另外的文章,文章有实现源代码,至于登陆我最后会说明 2, 获取群成员 public List<QQGroupMemberInfo> GetMemberInfo(GroupInfo gInfo)
{ if (!isLogin) Login();
List<QQGroupMemberInfo> gmis = new List<QQGroupMemberInfo>();
int page = 1;
int pageCount = 0;
GETMEMBER: string memberURL = string.Format(groupMemberUrl, gInfo.Number, page, JavascriptAction.Random());
string html = GetWebData<string>(memberURL);
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html); if (pageCount < 1)
{ var seeBtn = doc.DocumentNode.SelectSingleNode(pageBtnPath); pageCount = Convert.ToInt32(seeBtn.Attributes["allpage"].Value);
} var trs = doc.DocumentNode.SelectNodes(memberTrPath); foreach (var tr in trs)
{ var tds = tr.Descendants("td").ToList();
if (tds.Count < 1) continue;
string groupNick = tds[1].Element("a").InnerText.Trim();
string qq = tds[2].Element("span").InnerText.Trim();
gmis.Add(new QQGroupMemberInfo()
{ NickName = groupNick, QQ = qq }); } if (page < pageCount)
{ page++; goto GETMEMBER;
} return gmis;
} 上面的函数实现了群成员的获取,其中HTML的解析式通过HtmlAgilityPack(http://htmlagilitypack.codeplex.com/)来实现,HtmlAgilityPack通过XPATH语法去解析实现的,关于xpath不是很难,大家查查资料就会了 public class LoginQQ : WebPageAction, ILogin, IValidateCodeAction
{ static JavaScriptEngine _javaEngine = new JavaScriptEngine();
static bool _isInitJava = false;
Random _r = new Random();
const string loginFormUrl = "http://ui.ptlogin2.qq.com/cgi-bin/login?link_target=blank&appid=15000101&hide_title_bar=1&s_url=http%3A%2F%2Fim.qq.com%2Floginproxy.html%3Flogin_level%3D2&f_url=loginerroralert&target=self";
private User User { get; set; }
string _qq = "";
public LoginQQ(CookieManager cookieManager, User user)
: base(user.UserName)
{ _cookieManager = cookieManager; User = user; _qq = user.UserName.Split('@')[0];
if (!_isInitJava)
{ _javaEngine.Run(System.IO.File.ReadAllText(@"JavaScript\qq\md5_3.js"));
_isInitJava = true;
} } public override JavaScriptEngine JavaScriptEngine
{ get { return _javaEngine;
} set { _javaEngine = value;
} } string vc_type = "";
public bool Login(string referer)
{ DateTime beginTime = DateTime.Now; string html = "";
html = GetWebData<string>(loginFormUrl);
if (!regForm.IsMatch(html))
ThrowException(507, html); var form = GetFormDataByFormHtml(regForm.Match(html).Value); string url = "http://ptlogin2.qq.com/check?uin=" + _qq + "&appid=15000101&" + JavascriptAction.Random();
html = GetWebData<string>(url, referer: loginFormUrl);
string vcode = "";
if (html.Contains("ptui_checkVC('1','"))
{ vc_type = html.Replace("ptui_checkVC('1','", "").Replace("'", "").Replace(")", "").Replace(";", "");
form = new NameValueCollection();
if (!ValidationImageCode(form, loginFormUrl)) { return false; };
vcode = form["verifycode"];
} else if (html.Contains("ptui_checkVC('0','"))
{ vcode = html.Replace("ptui_checkVC('0','", "").Replace("'", "").Replace(")", "").Replace(";", "");
} TimeSpan _tspan = TimeSpan.FromTicks(DateTime.Now.Ticks - beginTime.Ticks); if (_tspan.Seconds < 20)
Thread.Sleep(TimeSpan.FromSeconds(_r.Next(20 - _tspan.Seconds, 30))); string pMd5 = GetPwdString(User.Pwd, vcode);
string action = "0-0" + "-" + (JavascriptAction.GetTime(DateTime.Now) - JavascriptAction.GetTime(beginTime));
url = "http://ptlogin2.qq.com/login?u=" + _qq + "&p=" + pMd5 + "&verifycode=" + vcode + "&aid=15000101&u1=http%3A%2F%2Fim.qq.com%2Floginproxy.html%3Flogin_level%3D2&h=1&ptredirect=0&ptlang=2052&from_ui=1&dumy=&fp=loginerroralert&action=" + action + "&mibao_css=";
html = GetWebData<string>(url, referer: loginFormUrl);
if (html.Contains("登录成功"))
{ return true;
} return false;
} private string GetPwdString(string pwd, string vcode)
{ string script = "md5(md5_3('" + pwd + "') + '" + vcode + "')";
return JavaScriptEngine.Run(script).ToString();
} public bool ValidateLogin(string referer)
{ var cks = _cookieManager.GetCookies(new Uri(referer).Host);
if (cks["uin"] != null && cks["skey"] != null)
{ return true;
} return false;
} public bool ValidationCode(string code, string referer)
{ return true;
} public Image GetValidateCode(string referer)
{ string url = "http://captcha.qq.com/getimage?aid=15000101&r=" + JavascriptAction.Random() + "&uin=" + _qq + "&vc_type=" + vc_type;
return GetWebData<Image>(url, referer: referer);
} public bool ValidationImageCode(NameValueCollection customFormItems, string referer)
{ ValidateReturn code = null;
do
{ Image image = GetValidateCode(referer); code = this.FireValidateCode(image);
if (code.IsCancel)
{ return false;
} if (customFormItems.AllKeys.Contains("verifycode"))
{ customFormItems.Remove("verifycode");
} customFormItems.Add("verifycode", code.Code);
} while (code.IsChange || !ValidationCode(code.Code, referer));
return true;
} } 第二种就是从客户端点击,如QQ空间按钮,客户端会调用浏览器跳转 http://ptlogin2.qq.com/jump?ptlang=2052&clientuin=442799037&clientkey=687E58BB1B99061A S62F0C751CF1763F1A8EEA3E8F2AF52B7956193D947F78B6&u1=http%3A%2F%2Fuser.qzone.qq.com%2F442799037%2Finfocenter&ADUIN=442799037&ADSESSION=1335488190&ADTAG=CLIENT.QQ.3187_Mysrv.0这样的地址,通过这个URL实现登陆,那么我们只需要HOOK ShellExecuteExW这个入口点就可以实现URL的截取,关于钩子如何实现,我前面有文章已说过,同样贴上代码供大家参考 public class ClientQQWebction : WebPageAction, IDisposable
{ const string loginUrl = "http://ptlogin2.qq.com/jump?ptlang={2}&clientuin={0}&clientkey={1}&u1={3}";
const string getEmail = "http://accountadm.qq.com/cgi-bin/account/ajaxgetmail?uin={0}";
const string groupListUrl = "http://qun.qq.com/air/group/mine?w=a&_={0}";
const string groupMemberUrl = "http://qun.qq.com/air/{0}/addr/index/type/1/p/{1}?w=n&_={2}";
const string pageBtnPath = "//input[@type=\"button\" and @value=\"查看\" and @act=\"gotopage\"]";
const string memberTrPath = "//table[@class=\"addressList\"]/tr";
CleintKeyInfo _cleintKeyInfo = null;
bool isLogin = false;
public ClientQQWebction(CleintKeyInfo cki)
{ _cleintKeyInfo = cki; } private void Login()
{ string loginURL = string.Format(loginUrl, _cleintKeyInfo.ClientUin, _cleintKeyInfo.ClientKey, _cleintKeyInfo.PtLang, string.Format(getEmail, _cleintKeyInfo.ClientUin));
var loca = GetWebData<ResponseLocation>(loginURL); if (_cookieManager.GetCookies("qq.com")["skey"] != null)
{ isLogin = true;
return;
} throw new Exception("登陆失败");
} public string GetEmail()
{ if (!isLogin) Login();
string emailUrl = String.Format(getEmail, _cleintKeyInfo.ClientUin);
var html = GetWebData<string>(emailUrl);
if (regEmail.IsMatch(html))
return regEmail.Match(html).ToString();
else
return null;
} public List<GroupInfo> GetGroupInfos()
{ if (!isLogin) Login();
List<GroupInfo> giList = new List<GroupInfo>();
string json = GetWebData<string>(string.Format(groupListUrl, JavascriptAction.Random()));
try
{ var jsonObj = JavaScriptEngine.Run("var m=" + json + ";m.c") as Dictionary<string, object>;
foreach (var key in jsonObj.Keys)
{ var gi = (jsonObj[key] as Dictionary<string, object>);
if (!gi.ContainsKey("owner")) continue;
string owner = gi["owner"].ToString();
string name = gi["name"].ToString();
string max_member = gi["max_member"].ToString();
string create_time = gi["create_time"].ToString();
string notice = gi["brief"].ToString();
string number = key;
string memo = gi["memo"].ToString();
giList.Add(new GroupInfo()
{ CreateTime = JavascriptAction.GetTimeByJsTime(Convert.ToInt64(create_time)), MaxNumber = Convert.ToInt32(max_member), Memo = memo, Name = name, Notice = notice, Number = number, Owner = owner }); } } catch { }
return giList;
} public List<QQGroupMemberInfo> GetMemberInfo(GroupInfo gInfo)
{ if (!isLogin) Login();
List<QQGroupMemberInfo> gmis = new List<QQGroupMemberInfo>();
int page = 1;
int pageCount = 0;
GETMEMBER: string memberURL = string.Format(groupMemberUrl, gInfo.Number, page, JavascriptAction.Random());
string html = GetWebData<string>(memberURL);
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html); if (pageCount < 1)
{ var seeBtn = doc.DocumentNode.SelectSingleNode(pageBtnPath); pageCount = Convert.ToInt32(seeBtn.Attributes["allpage"].Value);
} var trs = doc.DocumentNode.SelectNodes(memberTrPath); foreach (var tr in trs)
{ var tds = tr.Descendants("td").ToList();
if (tds.Count < 1) continue;
string groupNick = tds[1].Element("a").InnerText.Trim();
string qq = tds[2].Element("span").InnerText.Trim();
gmis.Add(new QQGroupMemberInfo()
{ NickName = groupNick, QQ = qq }); } if (page < pageCount)
{ page++; goto GETMEMBER;
} return gmis;
} public void Dispose()
{ _cookieManager = null;
JavaScriptEngine = null;
} } OK,到此完成,下篇实现qq好友数据获取 最近失业了,求职中……… |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论