点击我前往Github查看源代码   别忘记star

本项目github地址:https://github.com/wangqifan/ZhiHu

UserManage是获取用户信息的爬虫模块

public   class UserManage
{
private string html; private string url_token; }

构造函数

用户主页的uRL格式为"https://www.zhihu.com/people/"+url_token+"/following";

 public UserManage(string urltoken)
{
url_token = urltoken;
}

先封装一个获取html页面的方法

 private bool GetHtml()

        {                

            string url="https://www.zhihu.com/people/"+url_token+"/following";

            html = HttpHelp.DownLoadString(url);

            return  !string.IsNullOrEmpty(html);

        }

拿到了html页面,接下来是剥取页面中的JSON,借助HtmlAgilityPack

public  void  analyse()
{
if (GetHtml())
{
try
{
Stopwatch watch = new Stopwatch();
watch.Start();
HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);
HtmlNode node = doc.GetElementbyId("data");
StringBuilder stringbuilder =new StringBuilder(node.GetAttributeValue("data-state", ""));
stringbuilder.Replace(""", "'");
stringbuilder.Replace("&lt;", "<");
stringbuilder.Replace("&gt;", ">"); watch.Stop();
Console.WriteLine("分析Html用了{0}毫秒", watch.ElapsedMilliseconds.ToString()); }
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
} }

添加用户的关注列表的链接

 private void  GetUserFlowerandNext(string json)

        {

                 string foollowed = "https://www.zhihu.com/api/v4/members/" + url_token + "/followers?include=data%5B*%5D.answer_count%2Carticles_count%2Cfollower_count%2Cis_followed%2Cis_following%2Cbadge%5B%3F(type%3Dbest_answerer)%5D.topics&offset=0&limit=20";

                 string following = "https://www.zhihu.com/api/v4/members/" + url_token + "/followees?include=data%5B%2A%5D.answer_count%2Carticles_count%2Cfollower_count%2Cis_followed%2Cis_following%2Cbadge%5B%3F%28type%3Dbest_answerer%29%5D.topics&limit=20&offset=0";

                 RedisCore.PushIntoList(, "nexturl", following);

                 RedisCore.PushIntoList(, "nexturl", foollowed);

        }

对json数据进一步剥取,只要用户的信息,借助JSON解析工具Newtonsoft.Json

private void  GetUserInformation(string json)
{
JObject obj = JObject.Parse(json);
string xpath = "['" + url_token + "']";
JToken tocken = obj.SelectToken("['entities']").SelectToken("['users']").SelectToken(xpath);
RedisCore.PushIntoList(, "User", tocken.ToString()); }
 
现在来完成下analyse函数
 public  void  analyse()
{
if (GetHtml())
{
try
{
Stopwatch watch = new Stopwatch();
watch.Start();
HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);
HtmlNode node = doc.GetElementbyId("data");
StringBuilder stringbuilder =new StringBuilder(node.GetAttributeValue("data-state", ""));
stringbuilder.Replace(""", "'");
stringbuilder.Replace("<", "<");
stringbuilder.Replace(">", ">");
GetUserInformation(stringbuilder.ToString());
GetUserFlowerandNext(stringbuilder.ToString());
watch.Stop();
Console.WriteLine("分析Html用了{0}毫秒", watch.ElapsedMilliseconds.ToString()); }
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
} }
}

  

UrlTask是从nexturl队列获取用户的关注列表的url,获取关注列表。服务器返回的Json的数据

封装一个对象的序列化和反序列化的类

public   class SerializeHelper
{
/// <summary>
/// 对数据进行序列化
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string SerializeToString(object value)
{
return JsonConvert.SerializeObject(value);
}
/// <summary>
/// 反序列化操作
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="str"></param>
/// <returns></returns>
public static T DeserializeToObject<T>(string str)
{ return JsonConvert.DeserializeObject<T>(str);
}
}

封装UrlTask类


 public class UrlTask
{
private string url { get; set; }
private string JSONstring { get; set; }
public UrlTask(string _url)
{
url = _url;
}
}

添加一个获取资源的方法


 private bool GetHtml()
{
JSONstring= HttpHelp.DownLoadString(url);
Console.WriteLine("Json下载完成");
return !string.IsNullOrEmpty(JSONstring);
}
解析json方法

 public  void  Analyse()
{
try
{
if (GetHtml())
{
Stopwatch watch = new Stopwatch();
watch.Start(); followerResult result = SerializeHelper.DeserializeToObject<followerResult>(JSONstring);
if (!result.paging.is_end)
{
RedisCore.PushIntoList(1, "nexturl", result.paging.next);
}
foreach (var item in result.data)
{
int type=Math.Abs(item.GetHashCode())% 3 + 3;
if (RedisCore.InsetIntoHash(type, "urltokenhash", item.url_token, "存在"))
{
RedisCore.PushIntoList(1, "urltoken", item.url_token); } }
watch.Stop();
Console.WriteLine("解析json用了{0}毫秒",watch.ElapsedMilliseconds.ToString());
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
} }

解析:如果result.paging.is_end为true,那么这个是用户关注列表的最后一页,那么它的nexturl应该加入队列,负责不要加入,对于后面的用户数组,因为信息不去全,不要了,有了Id前往主页获取详细信息。


模块组合

封装一个一个方法,从队列拿到nextutl,前往用户的关注列表,拿到更多用户ID

  private static void GetNexturl()
{
string nexturl = RedisCore.PopFromList(1, "nexturl");
if (!string.IsNullOrEmpty(nexturl))
{
UrlTask task = new UrlTask(nexturl);
task.Analyse();
}
}

封装一个方法,循环从队列获取用户的urltoken(如果队列空了,执行GetNexturl),前往用户主页,获取信息

private static void GetUser(object data)
{ while (true)
{
string url_token = RedisCore.PopFromList(1, "urltoken");
Console.WriteLine(url_token);
if (!string.IsNullOrEmpty(url_token))
{
UserManage manage = new UserManage(url_token);
manage.analyse();
}
else
{
GetNexturl();
}
} }

在main函数里面执行这些方法,由于任务量大,采用多线程,线程数视情况而定

for (int i = 0; i < 10; i++)

            {

                ThreadPool.QueueUserWorkItem(GetUser);

            }

添加种子数据,用于刚开始时候队列都是空的,需要添加种子数据

  1. 手动添加,在redile-cl.exe敲命令
  2. 在main函数中加入
 UserTask task=new UserTask(“某个用户的uRLtoken”);

               task.analyse();

执行一次之后要注释掉,避免重复

爬去知乎百万用户信息之UserTask的更多相关文章

  1. 爬取知乎百万信息之UrlTask

    这个模块的作用是从nexturl队列获取用户的关注列表的url,获取关注列表.服务器返回的Json的数据 封装一个对象的序列化和反序列化的类 public class SerializeHelper ...

  2. web scraper——爬取知乎|微博用户数据模板【三】

    前言 在这里呢,我就只给模板,不写具体的教程啦,具体的可以参考我之前写的博文. https://www.cnblogs.com/wangyang0210/p/10338574.html 模板 进入微博 ...

  3. 利用 Scrapy 爬取知乎用户信息

    思路:通过获取知乎某个大V的关注列表和被关注列表,查看该大V和其关注用户和被关注用户的详细信息,然后通过层层递归调用,实现获取关注用户和被关注用户的关注列表和被关注列表,最终实现获取大量用户信息. 一 ...

  4. [Python爬虫] Selenium爬取新浪微博客户端用户信息、热点话题及评论 (上)

    转载自:http://blog.csdn.net/eastmount/article/details/51231852 一. 文章介绍 源码下载地址:http://download.csdn.net/ ...

  5. 使用python scrapy爬取知乎提问信息

    前文介绍了python的scrapy爬虫框架和登录知乎的方法. 这里介绍如何爬取知乎的问题信息,并保存到mysql数据库中. 首先,看一下我要爬取哪些内容: 如下图所示,我要爬取一个问题的6个信息: ...

  6. Python爬虫从入门到放弃(十八)之 Scrapy爬取所有知乎用户信息(上)

    爬取的思路 首先我们应该找到一个账号,这个账号被关注的人和关注的人都相对比较多的,就是下图中金字塔顶端的人,然后通过爬取这个账号的信息后,再爬取他关注的人和被关注的人的账号信息,然后爬取被关注人的账号 ...

  7. 爬虫(十六):scrapy爬取知乎用户信息

    一:爬取思路 首先我们应该找到一个账号,这个账号被关注的人和关注的人都相对比较多的,就是下图中金字塔顶端的人,然后通过爬取这个账号的信息后,再爬取他关注的人和被关注的人的账号信息,然后爬取被关注人的账 ...

  8. Python之爬虫(二十) Scrapy爬取所有知乎用户信息(上)

    爬取的思路 首先我们应该找到一个账号,这个账号被关注的人和关注的人都相对比较多的,就是下图中金字塔顶端的人,然后通过爬取这个账号的信息后,再爬取他关注的人和被关注的人的账号信息,然后爬取被关注人的账号 ...

  9. 基于webmagic的爬虫小应用--爬取知乎用户信息

    听到“爬虫”,是不是第一时间想到Python/php ? 多少想玩爬虫的Java学习者就因为语言不通而止步.Java是真的不能做爬虫吗? 当然不是. 只不过python的3行代码能解决的问题,而Jav ...

随机推荐

  1. SPRING IN ACTION 第4版笔记-第九章Securing web applications-008-使用非关系型数据库时如何验证用户(自定义UserService)

    一. 1.定义接口 Suppose that you need to authenticate against users in a non-relational database suchas Mo ...

  2. Mac与Linux的一个巨大不同

    就是Mac仍处在桌面市场的商业圈里,尽管它的市场很小,但是正版率却很高,而且还有专门的Mac Store提供付费下载. Linux在桌面市场几乎没有份额,也不会有人会去买它的应用软件,基本上只存在于服 ...

  3. 211. Add and Search Word - Data structure design

    题目: Design a data structure that supports the following two operations: void addWord(word) bool sear ...

  4. cookie分析

    浏览器cookie分析 简单点说就是数据存储,通过JavaScript将要保存的数据保存在客户端浏览器,下次打开网页时调用保存的cookie.浏览器中cookie保存的形式:user=aa; pwd= ...

  5. poj 3321 Apple Tree(一维树状数组)

    题目:http://poj.org/problem?id=3321 题意: 苹果树上n个分叉,Q是询问,C是改变状态.... 开始的处理比较难,参考了一下大神的思路,构图成邻接表 并 用DFS编号 白 ...

  6. BZOJ_1027_[JSOI2007]_合金_(计算几何+Floyd求最小环)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1027 共三种金属,\(m\)种材料,给出每种材料中三种金属的占比. 给出\(n\)种合金的三种 ...

  7. angularjs filter 详解

    系统的学习了一下angularjs,发现angularjs的有些思想根php的模块smarty很像,例如数据绑定,filter.如果对smarty比较熟悉的话,学习angularjs会比较容易一点.这 ...

  8. MySQL InnoDB存储引擎中的锁机制

    1.隔离级别 Read Uncommited(RU):这种隔离级别下,事务间完全不隔离,会产生脏读,可以读取未提交的记录,实际情况下不会使用. Read Committed (RC):仅能读取到已提交 ...

  9. 《深入Java虚拟机学习笔记》- 第17章 异常

    <深入Java虚拟机学习笔记>- 第17章 异常

  10. 判断A树是否包含B树结构

    题目:输入两棵二叉树A和B,判断B是不是A的子结构 分析:根据数的遍历方法,首先想到的是采用递归的方式要更简单些,树A从根节点进行遍历,首先判断与B的根节点值是否相等,如果相等则进行递归遍历验证,否则 ...