问:能利用爬虫技术做到哪些很酷很有趣很有用的事情?
今天突然想玩玩爬虫,就提了这个问题。随着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
步入正题,思路描写:
<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段:
</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,名称等数据。
{
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
以下是程序主窗体源码:
{
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
{
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
/// 知乎问题数据表操作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 && ᨲ鱸ÇÇ⚶ﭺ嫭蛿윺ꕎ腄衐⬤첁ꍪ쪀ྤ㐉妐揉䂲▱䧅䈩∧䤄閵ᢙꈴᦉ‴आᤩ꘤䤂ꒁ级鿩俐헕掱롸羖껡㺵��⎾ɂ꩒ሴ붤ﭽ粰髹}忺磩ꄲ쿚㭅吺꺤絞⨏痦襸鞘詨韠⩳㕌蝹䴒壉턼骢⎪勰標째죶俶섾゚䧸ﱛ瞴䯆ﱤ轧䭲ﳷ燱ﱺ쓻ᴗ﮿鴢╉ⴓ濴㑇튡玙����䏿㉳��躑짿��槰过矲勞旙ꓩ瓱녽��軿퇾俧ﲺ쯙閹습맵㙜宛熹䳄羡荷ꓔ턴籕��ﯳ꧆䣫빱ꛯ㴿㽆鿼ம藹��坢槨﹡慾Ꞵ��ㄕஏ靣︽Ὠ봯䟱爖駙쏼ﲮ뷻ﻋ잵楱籘⓰횿羕춝ꏾ喇Ꮋ콁쩺㷋맧訯圗娩䴖낭嚼뮘宜��㑳煨굾歴鿞䢿穖䕨培拾⍋蓴댖줝㚶瞿缥맣滛ꇽ㐛展ⴛ῞Ꮄ렡ꊾ渎쎛談콫��ﺇ㦝耗얹㐠ﯷ䩺䏝犑��ꈝ︉滼㬩迣팎緽觹뒧죓촂㼶騲ᵛ៷誖믐皁繂糰��緊優ጏ㳽뾕䵵濤��寸ⓗ㍭ㇰ薀꓆朧ដﰖㇹꭧ럼뵚︽꽴댿䃂绪샃忎䩾끫䝃哪毚髳䍉抝��矟⧕폠뿃穷麝뉽躻흎備쾣⯨鉺見淽㪝伛櫬ྰむ껅ꁮ걫횸ᡛ尟䟴靮䝺敨䞅秧厉貣菣뒽뙐ﻹ홰绯ᾕ쟮킐煿땾㊰䎻佇ḵᅬ
波比源码 » 被管理员和谐了的最高票答案“知乎数据抓取程序”(.net、c#数据挖掘)
levofloxacin 250mg generic buy levofloxacin 250mg online cheap
accutane 20mg price order deltasone 5mg pills prednisone 20mg ca
purchase viagra online cheap viagra 100 mg lisinopril 2.5mg sale
order colchicine 0.5mg generic colchicine 0.5mg us online casino slots no download
buy deltasone 40mg accutane 20mg oral amoxicillin 250mg cost
order tadalafil 40mg Cialis price tadalafil over counter
buy ramipril 5mg for sale order ramipril 10mg for sale buy arcoxia 60mg without prescription
buy term papers online cheap essay help buy generic azulfidine 500 mg
generic lanoxin lanoxin 250mg for sale molnunat us
coreg 25mg pills ditropan 2.5mg over the counter amitriptyline over the counter
order pepcid 20mg pills order generic prograf 1mg buy remeron 30mg for sale
order cialis 40mg sale home remedies for ed erectile dysfunction online ed pills
buy modafinil 100mg without prescription promethazine without prescription buy phenergan online
brand accutane 40mg prednisone 20mg canada ampicillin order online
buy ed pills for sale buy propecia 5mg pills proscar for sale online
order zofran 4mg pill buy amoxil pill sulfamethoxazole pill
accutane buy online amoxicillin generic order zithromax 250mg generic
albuterol canada oral augmentin 1000mg augmentin for sale online
doxycycline 100mg brand order doxycycline 100mg online cheap zovirax 400mg pills
order avodart generic buy keflex 125mg for sale buy orlistat for sale
buy cefdinir 300 mg generic order prevacid for sale pantoprazole 20mg pill