最新公告
  • 欢迎您光临波比源码,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入我们
  • 被管理员和谐了的最高票答案“知乎数据抓取程序”(.net、c#数据挖掘)

    问:能利用爬虫技术做到哪些很酷很有趣很有用的事情?

    准备学习python爬虫。各位大神都会用爬虫做哪些有趣的事情?

    今天突然想玩玩爬虫,就提了这个问题。随着YouTube上的1个tutor写了个简单的程序,爬了1点豆瓣的数据。主要用到request和bs4(BeautifulSoup)模块。虽然简陋,毕竟是人生中的第1只爬虫啊……以示记念,代码写在博客里了:我的第1只爬虫:爬取豆瓣读书

    没想到第1次答题竟然登上了知乎互联网专栏的榜首了,也上了知乎首页,惋惜被和谐了。

    答:

    监测她(他)的知乎,她关注、回答、赞了某个问题立马电脑和手机都弹出提示是否是很酷!先上两张图:


    我是个.NET程序猿,有1天女神告知我有1个很不错的社区叫“知乎”,我常常1过来就看到她在看知乎,但每次我想看她都看了啥啊,她就遮住屏幕不让我看。因而乎,在我心里埋下了1颗强烈的好奇心。知乎中搜了下她的名字,经过各种挑选知道了她的知乎空间。第1时间出现的想法是我要写个监测程序,她关注的所有问题我都想知道。
    连续奋战5小时,至清晨3点程序终究写出来了。主要HttpWebRequest加正则表达式来抓取数据,程序开机自动运行,数据库设在1台24小时开机的服务器上。多个监测客户端同时运行,公司的,家里的,远程服务器上的。每隔5分钟自动循环读取1次数据,如果检测到关注了新的问题,立马将它们发送至我的QQ邮箱和我的163邮箱,大家都知道QQ邮箱有提示功能,1发过来,立马会弹出1个窗体告知你有新的邮件。手机qq客户端也有,所以不管我是在上班的路上,还是在电脑旁,只要她有新动态我立马就知道了。是否是很酷?
    监测程序已运行3个多月了,搜集了他23百个关注的问题,我知道她1般都是吃中饭或晚餐前喜欢看1下知乎,晚上睡前会看会,她睡得早但偶尔清晨1点多还看知乎。她关注情感类的问题最多,而且那段时间我1直在追她,所以我能根据她关注的问题来推测她的1些想法,包括约会聊天时我可以聊1些她感兴趣的话题。所以实用性还是比较强的。
    假设某1天清晨1点,手机突然响了1下,发现她关注了某个问题。立马给她发1条短信过去,你是否是还没睡啊?
    是啊,你怎样知道我没睡的? 凭感觉! 嘿嘿。 然后渐渐靠近她关注的那个话题去聊,这是否是会让她感觉到你特别懂她。好奇你竟然知道她睡没睡,好奇你和她聊的话那末符合她的心声。

    如此利器,有谁想要的吗? 赞超过1百,程序和源代码都放知乎上同享。

    ====21日9:37更新=====
    没想到第1次答题就上榜了,好不开心,来来来,别停哈。怒上榜首,我开源12306抢票源码。我先赴约去开源我的知乎监测程序吧,1会把链接发过来。谢谢大家的赞!


    ===============


    ====21日11:50更新=====
    《关于隐私》
    先说明下,很多人都说我这样做侵犯隐私?没有吧,这些数据都是公然的啊,她也知道我关注了她呀,但蛋疼的知乎客户端没有这么细致的提示功能,我乃至在客户端上找不到我都关注了哪些人。知乎手机app开发团队弱爆了,这么强有力的需求竟然没有满足?
    而且,知乎!你怎样就没有定阅功能呢?邮箱定阅! 我提出来啦哈,采用了给我大V可好?

    《关于匿不匿名》
    FK,男子汉大丈夫,匿啥名啊。女神知道了就知道了,又不是做甚么丧尽天良的事,敢作敢当!之所以写这么1个程序,也其实不是完全的偷窥心理。对1个程序员来讲,写出1个新鲜的程序是能给程序员1种很大的乐趣的,这1般人难以理解,想当年在学校时,通宵写俄罗斯方块,白天上课不听课在那研究1个方块当按左键是甚么模样甚么逻辑,右键又怎样。这是非常成心思的事,编程实际上是1个艺术活,好的框架和优良的代码让人1看就感觉特别享受。
    所以我写这么个程序一样也是满足自己的1种乐趣。没必要匿!

    《关于女神追到没?》
    追到啦,哈哈!好爽啊,9月份去骑了趟川藏线,路遇佛像及经轮,我就祈祷我要娶她做老婆。且动身前找牛逼大神算了1卦(中国易学协会副会长),说我10月份很有姻缘缘分。因而,我在世界3大冰川之1的-来古冰川的河床上找了1下午的石头,终究找到1颗天然红色心形的爱情石,回来后我就拿着石头跟她表白了,然后就成了!虽然她说我表白像检讨1样,但也很感人!
    惋惜,我们在1起没多久就分手了。缘由1两句话说不完,总之不管以后怎样。都祝愿她,虽然在1起不长时间,但那是很美的回想。我会收藏!
    ===================


    =====2015⑴⑵1 上午11:16分更新=======

    程序开源地址:

    下载源程序http://download.csdn.net/detail/wuyidexinsheng/8382253
    程序博文地址:http://blog.csdn.net/wuyidexinsheng/article/details/42964707


    步入正题,思路描写:

    下来源程序后,先自己去建数据库改配置哈,否则程序运行不起来的。

    <span style="font-size:10px;"><?xml version="1.0"?>
    <configuration>
    <appSettings>
    <!–数据有两种存储方式,1种存储于本地程序目录下的Ids.txt,但那只存了问题ID,完全的数据存于oracle数据库中–>
    <add key="connStr" value="Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=DZZH)));User Id=xxxxx;Password=xxxx"/>
    <!– 设置监测循环时间:秒 –>
    <add key="Interval" value="600"/>
    <!–设置自动发送信息机器人邮箱–>
    <add key="smtpAddress" value="smtp.163.com"/>
    <!–用户名–>
    <add key="sendEmailFrom" value="xxxxxxxx@163.com"/>
    <!–密码–>
    <add key="sendEmailFromPwd" value="xxxxxxxxx"/>
    <!–接收邮箱地址–>
    <add key="strMailAddressTo" value="xxxxxxxx@163.com,xxxxxxxx@qq.com"/>
    <!–邮件名称抬头–>
    <add key="EmailName" value="zhApp-家里电脑"/>
    <!–END–>
    <!–监测地址–>
    <add key="WatchingURL" value="http://www.zhihu.com/people/wu-xin-sheng⑺"/>
    </appSettings>
    <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
    </startup>
    </configuration></span>

    第1步:通过Cinser.Common.HttpHelper.GetString(“www.zhihu.com/people/wu-xin-sheng⑺”)读取给定的1个网址的后台代码:

    结果以下图所示:


    如我空间的源码中就有这么1段:

    <span class="name">伍新生</span>,<span class="bio" title="5颜6色的情感,我终生的寻求!">5颜6色的情感,我终生的寻求!</span>
    </div>
    </div>
    <div class="body clearfix">
    <div class="zm-profile-header-avatar-container self">
    <img alt="伍新生"
    src="http://pic4.zhimg.com/94cc60166_l.jpg"
    class="zm-profile-header-img zg-avatar-big zm-avatar-editor-preview"/>

    <span class="zm-entry-head-avatar-edit-button">修改头像</span>

    第2步:通过调用方法private List<Question> GetQuestions(string source)截取关键数据。

    原理很简单,所有知乎的问题都是以下的格式:<aclass="question_link"target="_blank"href="/question/27621722/answer/37636385">能利用爬虫技术做到哪些很酷很有趣很有用的事情?</a>

    接下来那就是字符串截取呗:调用Cinser.Common.StringPlus.SubString(source, “<a class="question_link”, "</a>")等顺次截取问题的ID,名称等数据。

    private List<Question> GetQuestions(string source)
    {
    List<Question> questions = new List<Question>();
    string startStr = "<a class="question_link"";
    if (source.IndexOf(startStr) != ⑴)
    {
    Question q = new Question();
    string content = Cinser.Common.StringPlus.SubString(source, startStr, "</a>");
    q.Id = Cinser.Common.StringPlus.SubString(content, "question/", """);
    q.Title = content.Substring(content.IndexOf(">") + 1);
    q.Time = DateTime.Now;
    questions.Add(q);
    source = source.Substring(source.IndexOf(startStr) + startStr.Length);
    questions.AddRange(GetQuestions(source));
    }
    return questions;
    }

    第3步:将取到的问题写入数据库,并写入本地Ids.txt。

    由于5分钟读取1次数据,肯定会读取到部份已度过的数据咯。就是通过取到id然后看Ids.txt里面这个id是否是已存在了,如果存在了就表示已抓去过啦。 

    为何问题都已写到oracle数据库了还要往本地Ids.txt写1次呢,由于oracle数据库是部署在远程服务器上的啊。如果这台服务器突然出故障死机了,怎样办?程序还得要运行啊,所以程序往两个地方都写1次数据。如果oracle数据库不能访问,则通过读取和写入本地ids来记录问题。


    数据抓取其实就这么简单。


    以下是部份源码,也能够直接去下载源程序:http://download.csdn.net/detail/wuyidexinsheng/8382253

    以下是程序主窗体源码:

    public partial class Form1 : Form
    {
    DataProvider dal;
    string watchingURL = string.Empty;
    int LoopCount = 0;
    public Form1()
    {
    InitializeComponent();
    dal = new DataProvider();
    dal.AddLog("程序启动");

    base.WindowState = FormWindowState.Minimized;
    base.Show();
    base.Hide();
    base.WindowState = FormWindowState.Normal;
    base.ShowInTaskbar = false;
    base.TopMost = false;
    base.MaximizeBox = false;
    base.MinimizeBox = false;
    base.ControlBox = false;

    //设置循环监测时间
    int interval = int.Parse(Cinser.Common.ConfigurationHelper.GetAppSettingsValue("Interval"));
    timer1.Interval = interval * 1000;

    watchingURL = Cinser.Common.ConfigurationHelper.GetAppSettingsValue("WatchingURL");
    RunWhenStart(true, "zhApp.exe", """ + Application.StartupPath + "zhApp.exe" AutoRun");
    Run();
    dal.AddLog("程序初始化成功");
    LoopCount += 1;
    }

    //设置程序开机自启动
    public void RunWhenStart(bool Started, string name, string path)
    {
    RegistryKey HKLM = Registry.CurrentUser;
    RegistryKey Run = HKLM.CreateSubKey(@"SOFTWAREMicrosoftWindowsCurrentVersionRun");
    if (Started == true)
    {
    try
    {
    Run.SetValue(name, path);
    HKLM.Close();
    }
    catch(Exception ex)//没有权限会异常
    {
    throw ex;
    }
    }
    else
    {
    try
    {
    Run.DeleteValue(name);
    HKLM.Close();
    }
    catch (Exception ex)//没有权限会异常
    {
    throw ex;
    }
    }
    }

    /// <summary>
    /// 运行监测流程
    /// </summary>
    private void Run()
    {
    List<Question> questions = GetQuestions(Cinser.Common.HttpHelper.GetString(watchingURL));
    string ids = dal.GetExistIdsStr();
    for (int i = 0; i < questions.Count; i++)
    {
    if (ids.IndexOf(questions[i].Id) != ⑴)
    {
    questions.Remove(questions[i]);
    i–;
    }
    else
    {
    if (ids == string.Empty)
    ids = questions[i].Id;
    else
    ids += "," + questions[i].Id;
    }
    }
    if (questions.Count > 0)
    {
    SendQuestions(questions);
    dal.WriteIdStrToTxt(ids);
    dal.Add(questions);
    dal.AddLog(string.Format("获得了{0}条新数据。", questions.Count));
    }
    }

    /// <summary>
    /// 从监测站点源数据中抓取问题
    /// </summary>
    private List<Question> GetQuestions(string source)
    {
    List<Question> questions = new List<Question>();
    string startStr = "<a class="question_link"";
    if (source.IndexOf(startStr) != ⑴)
    {
    Question q = new Question();
    string content = Cinser.Common.StringPlus.SubString(source, startStr, "</a>");
    q.Id = Cinser.Common.StringPlus.SubString(content, "question/", """);
    q.Title = content.Substring(content.IndexOf(">") + 1);
    q.Time = DateTime.Now;
    questions.Add(q);
    source = source.Substring(source.IndexOf(startStr) + startStr.Length);
    questions.AddRange(GetQuestions(source));
    }
    return questions;
    }

    private bool SendQuestions(List<Question> questions)
    {
    bool bSuccess = true;
    List<string> strMailAddressTo = Cinser.Common.ConfigurationHelper.GetAppSettingsValue("strMailAddressTo").Split(',').ToList();
    string smtpAddress = Cinser.Common.ConfigurationHelper.GetAppSettingsValue("smtpAddress");
    string sendEmailFrom = Cinser.Common.ConfigurationHelper.GetAppSettingsValue("sendEmailFrom");
    string sendEmailFromPwd = Cinser.Common.ConfigurationHelper.GetAppSettingsValue("sendEmailFromPwd");
    string emailName = Cinser.Common.ConfigurationHelper.GetAppSettingsValue("EmailName");
    //密码解密,开源的话就去掉这步吧,这样配置的时候直接配置明文密码就行。
    //sendEmailFromPwd = Cinser.Common.Security.DecryptDES(sendEmailFromPwd, "yuiophgf");
    string msg = string.Empty;
    SendCompletedEventHandler s = new SendCompletedEventHandler(SendCompleted);
    string content = GetQustionsListStr(questions);
    content += "

    信息来源于:" + watchingURL;
    Cinser.Common.SmtpEmailSend.SendEmail(strMailAddressTo, emailName + DateTime.Now.ToString(), content, smtpAddress, 0x19, sendEmailFrom, sendEmailFromPwd, "163测试邮箱", null, out msg, s);
    return bSuccess;
    }

    private void SendCompleted(object sender, AsyncCompletedEventArgs e)
    {
    }

    private string GetQustionsListStr(List<Question> questions)
    {
    string content = string.Empty;
    if (questions != null && questions.Count > 0)
    {
    content = string.Format("名称:{0},url:{1}", questions[0].Title, questions[0].Url);
    for (int i = 1; i < questions.Count; i++)
    {
    content += string.Format("
    名称:{0},url:{1}", questions[i].Title, questions[i].Url);
    }
    }
    return content;
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
    int interval = int.Parse(Cinser.Common.ConfigurationHelper.GetAppSettingsValue("Interval"));
    timer1.Interval = interval * 1000;
    Run();
    dal.AddLog(string.Format("程序循环次数:{0}", LoopCount++));
    }
    }


    知乎问题model:Question.cs

    public class Question
    {
    string id, title, url, type, remark;
    DateTime time;

    public string Remark
    {
    get { return remark; }
    set { remark = value; }
    }

    public DateTime Time
    {
    get { return time; }
    set { time = value; }
    }

    public string Type
    {
    get { return type; }
    set { type = value; }
    }

    public string Url
    {
    get
    {
    if (string.IsNullOrEmpty(url))
    {
    url = string.Format("http://www.zhihu.com/question/{0}", Id);
    }
    return url;
    }
    set { url = value; }
    }

    public string Title
    {
    get { return title; }
    set { title = value; }
    }

    public string Id
    {
    get { return id; }
    set { id = value; }
    }
    }

    数据操作类DataProvider.cs

    /// <summary>
    /// 知乎问题数据表操作Provider
    /// </summary>
    public class DataProvider
    {
    private string connStr = string.Empty;
    Cinser.DBUtility.DAL.OracleDALCommon dal;
    string txtPath = "";
    string logPath = "";
    string debugPath = string.Empty;

    public string DebugPath
    {
    get
    {
    if (debugPath == string.Empty)
    debugPath = System.AppDomain.CurrentDomain.BaseDirectory;

    if (debugPath.EndsWith("") == false)
    {
    debugPath += "";
    }
    return debugPath;
    }
    set { debugPath = value; }
    }

    public string LogPath
    {
    get
    {
    if (logPath == string.Empty)
    {
    logPath = DebugPath + "Log.txt";
    }
    return logPath;
    }
    }

    public DataProvider()
    {
    dal = new Cinser.DBUtility.DAL.OracleDALCommon(this.ConnStr);
    }

    public string TxtPath
    {
    get
    {
    if (txtPath == string.Empty)
    {
    txtPath = DebugPath + "Ids.txt";
    }
    return txtPath;
    }
    }

    public string ConnStr
    {
    get
    {
    if (connStr == string.Empty)
    {
    connStr = Cinser.Common.ConfigurationHelper.GetAppSettingsValue("connStr");
    }
    return connStr;
    }
    set { connStr = value; }
    }

    public bool CanConnectOracleServer
    {
    get
    {
    return dal.Open();
    }
    }

    /// <summary>
    /// 将抓取到的问题写入oracle数据库中
    /// </summary>
    /// <param name="questions"></param>
    /// <returns></returns>
    public bool Add(List<Question> questions)
    {
    bool bReturn = false;
    try
    {
    for (int i = 0; i < questions.Count; i++)
    {
    dal.Add("qustions", questions[i]);
    }
    bReturn = true;
    }
    catch { }
    return bReturn;
    }

    public DataTable GetQustions(string sqlWhere = "1=1")
    {
    try
    {
    DataTable dt = dal.GetDataList("qustions", sqlWhere);
    return dt;
    }
    catch
    {
    return null;
    }
    }

    public bool IsExist(string id)
    {
    try
    {
    string sqlWhere = "id='" + id + "'";
    DataTable dt = dal.GetDataList("qustions", sqlWhere);
    return dt.Rows.Count > 0;
    }
    catch
    {
    return false;
    }
    }

    /// <summary>
    /// 获得已抓取过的问题ID字符串
    /// </summary>
    /// <returns></returns>
    public string GetExistIdsStr()
    {
    string ids = string.Empty;
    //如果能连上远程的oracle服务器则从oracle数据库中取ID字符串
    if (CanConnectOracleServer)
    {
    DataTable dt = GetQustions();
    if (dt != null && ᨲ鱸Ç૴Ç⚶ﭺ嫭蛿윺ꕎ腄衐⬤첁ꍪ쪀ྤ㐉妐揉䂲▱䧅䈩∧䤄閵ᢙꈴᦉ‴आᤩ꘤䤂ꒁ级鿩俐헕掱롸羖껡㺵��⎾ɂ꩒ሴ붤ﭽ粰髹}￳忺磩ꄲ쿚㭅吺꺤絞⨏痦襸鞘詨韠⩳㕌蝹䴒壉턼骢⎪勰標째죶俶섾゚䧸ﱛ瞴䯆ﱤ轧䭲ﳷ燱ﱺ쓻ᴗ﮿鴢╉ⴓ濴㑇튡玙����䏿㉳��躑짿��槰过￟矲勞旙ꓩ瓱녽��軿퇾俧ﲺ쯙閹습맵㙜宛熹䳄羡荷ꓔ턴籕��ﯳ꧆䣫빱ꛯ㴿㽆鿼ம藹��坢槨﹡慾Ꞵ��ㄕஏ靣︽Ὠ봯䟱爖駙쏼ﲮ⹟뷻ﻋ잵楱籘⓰횿羕춝ꏾ喇Ꮋ콁쩺㷋맧訯圗娩䴖낭嚼뮘宜��㑳煨굾歴鿞䢿穖䕨培拾⍋蓴댖줝㚶瞿缥맣滛ꇽ㐛展ⴛ῞Ꮄ렡⿤ꊾ渎쎛談콫��ﺇ㦝耗얹୥㐠ﯷ䩺䏝犑��ꈝ︉滼㬩迣팎଴緽觹뒧죓촂㼶騲ᵛ៷誖믐皁﫾繂糰��緊優ጏ㳽뾕䵵濤��寸ⓗ㍭ㇰ薀꓆朧ដﰖㇹꭧ럼᤯뵚︽꽴댿䃂绪샃忎䩾끫䝃哪毚髳䍉抝��矟⧕폠뿃穷麝뉽躻흎備쾣⯨鉺見淽㪝伛櫬ྰむ껅ꁮ꥜걫횸ᡛ尟䟴靮䝺敨䞅秧厉貣菣뒽뙐ﻹ홰绯ᾕ쟮⳴킐煿땾㊰䎻佇ḵᅬ

    波比源码 – 精品源码模版分享 | www.bobi11.com
    1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
    2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
    3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
    4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
    5. 如有链接无法下载、失效或广告,请联系管理员处理!
    6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
    7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!

    波比源码 » 被管理员和谐了的最高票答案“知乎数据抓取程序”(.net、c#数据挖掘)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    波比源码
    一个高级程序员模板开发平台
    升级波友尊享更多特权立即升级