背景:实验室大数据分析需要得到社交网站的数据,首选当然是新浪。数据包括指定关键词、话题、位置的微博的内容。字段包括:图片、时间、用户、位置信息。

思路分析:要爬新浪的数据主要有2种方法:

1.微博开发者平台提供的微博API,资源包括微博内容、评论、用户、关系、话题等信息。同时,你也可以申请高级接口、商业接口获得更多权限,你要去注册申请成为开发者获得OAuth2授权以及这个使用参考,审核大约要1周。也可以直接使用别人分享的APPKEY。

优点是简单,有专门的问答社区,代码更新方便,可以获得real time的数据,对热门话题比较开放,返回的文档主要是json有很多现成的库类可以解析。 缺点是,数据受API规定,没有关键词检索,对不嗯呢该有访问次数限制,毕竟人家主要是服务微博的第三方应用,这个缺陷可以用更换上面的appkey来解决。

2.传统html爬虫,即发送http请求返回html源文件,再解析,提取里面的下级URL或者其他我们要的数据。C#.JAVA python都有相关的网页工具,c#主要是WebClient,或者HttpRequest/HttpResponse,也可以使用WebBrowser/page/htmldocument模拟浏览器操作,Java可以使用htmluint包。python对web处理的强大支持,使得网上的很多爬虫都是用python写的。

实现方法

  由于实验室要采集的量比较大,就先选择第二种试试看。首先分析一下微博的网页。首先是按关键字搜索微博,可以使用高级搜索进行过滤,选着原创和含图片选项,过滤掉转发的重复内容和不含图片的微博。问题是改版后的微博搜索只能显示第一页,后面内容需要登陆才能看的。所以我们的爬虫程序首要通过登陆这一关。微博的验证码可以手动取消,位置如下图:

1.登陆

  我知道的登陆的方法有3种。

  1,模拟登陆过程。C#地webBrowser封装了操控浏览器的方法,根据ID获取HTML上的控件填充表单,点击登陆等,非常的人性化操作,但是需要识别验证码的代码。

  2,模拟登陆POST,要用到抓包工具,比如burpsuite。这可能需要了解JS加密方法,以及验证码,具体网上找找。

  3。第三种比较简单,模拟登陆后状态。到浏览器找与s.weibo.com连接的heards,提取COOKIE字段加入到代码作为heard一起发送request。具体是打开网站-》F12-》NetWor选项卡-》Documents / Scripts-》点个文件看看-》heards的Hosst是不是s.weibo.com,是的话把里面的cookie复制下来。注意cookie阁段时间会变化。由于只要登陆一次就能取数据,为了节省时间我就用了第三种方法。

2.获得html源文件

  要获得源文件首先要向服务器发送访问请求。新浪微博搜索的URL是:http://s.weibo.com/wb/xiada&xsort=time 。仔细看会发现是像php命令风格的url:

1.其中s.weibo.com是Host。 /wb/是指搜微博,综合搜索的话是/weibo/,找人的话是/user/,图片是/pic/。注意这里的搜的据我观察好像是用户使用发微博功能现拍的单图内容,所以内容少很多。

  2.接着xiada就是搜索的关键词了,如果是中文关键词,这个字段就是经URLEncode编码的字符串。

3.Xsort=time 是搜索结果按时间排序,

  4.page=2,就是页数了,没有写就是第一页啦。可以通过更换page=多少来实现翻页。

  5.还有一些其他命令就不列举了,这些命令的可选值 都可以按"高级搜索" 选择你要的筛选条件再看看URL是什么样的就知道啦。

你可以做个界面让用户(也就是自己。。)来设置要搜什么样的微博。用HttpRequest 加上cookie 访问你通过上面命令生成的url,返回的就是网页源代码了。

3.解析html获取数据

  最关键的步骤就是怎么提取你的文档,假如你用c#的WebBrowser 那么恭喜你可以直接用Document类把html装进去,通过getItemById()之类的方法,根据标签头,直接提取标签内容,非常之方便。我是用正则表达式去源代码字符串里匹配我要的数据(图片链接,下层链接)。正则表达式C#参考这个,总结的够清楚。

  分析完这一样还要找下一页的超链接,在网页源码里搜"next",会发现只有一个,page next前面的herf="..."就是下一页的链接,可以根据这个来判断是不是最后一页。更快的方法是直接修改上面的命令page=n. 得到next page的url之后重复步骤2,3直到完成。

  需要注意的是微博的反爬虫机制,如果你短时间内请求30次左右,不管你登陆与否,会被警告然后让你输入验证。解决方法要么推送到软件上手动输入,要么用浏览器手动输入,要么加个验证码识别模块。自动验证码识别这个可以用htmlunit实现,我还在研究中。

4.源码

   这个程序适合入门学习,很多特性(存储策略,网络优化,性能)都没考虑进去,我这里贴出主要代码。主要部分实现细节可以参考http://www.cnblogs.com/Jiajun/archive/2012/06/16/2552103.html 这篇博客,思路大致一样,注释很详细,就是有点繁杂了,我借鉴了一点,非常之感谢。  

  另外有更多需求的同学可以去研究一下这个项目,在gihub有很多watch and fork,有API让你使用,而且有很多在爬到的数据可以下载,值得深入学习一下源码。

  1 namespace IMT.weiboSpider
  2 {
  3     class Spider
  4     {
  5         #region  field
  6         public List<WB_Feed> feedList { get; set; }
  7         private readonly object _locker = new object();
  8         private ThreadManager mThreadManager;//workManager.dowork_handler=
  9         public delegate void ContentsSavedHandler(string name);
 10         public delegate void DownloadFinishHandler(int count);
 11         public event ContentsSavedHandler ContentsSaved = null;
 12         public event DownloadFinishHandler DownloadFinish = null;
 13         public string _savePath;
 14         public string _url;
 15         public string _cookie;
 16         public string _next_url;
 17         public string _html;
 18         public int _count_current_URL;
 19         #endregion
 20
 21
 22         /// <summary>
 23         /// init
 24         /// </summary>
 25          public  Spider()
 26         {
 27             feedList = new System.Collections.Generic.List<WB_Feed>();
 28             mThreadManager = new ThreadManager(4);
 29             mThreadManager.dowork_handler += new ThreadManager.Do_a_Work_Handler(GetIMGDownload);
 30         }
 31         /// <summary>
 32         /// start working
 33         /// </summary>
 34         /// <param name="cookies"></param>
 35         public void Start(string cookies)
 36         {
 37             _cookie = cookies;
 38             Random rad=new Random();
 39             _html=GetHtmlDownload(_url, _cookie);
 40             _count_current_URL = GetHtmlPrased(_html);
 41             _next_url = GetNextHtmlUrl(_html);
 42             ContentsSaved.Invoke("url:[" + _url + "]IMG counts:" + _count_current_URL);
 43             while (!string.IsNullOrEmpty(_next_url))
 44             {
 45                 Thread.Sleep(rad.Next(1000,3000));
 46                 _html = GetHtmlDownload(_next_url, _cookie);
 47                 _count_current_URL = GetHtmlPrased(_html);
 48                 if (_count_current_URL < 2)
 49                 {
 50                     MessageBox.Show("需要手动刷新账号输入验证码,刷新后点再击确定");
 51                     continue;
 52                 }
 53                 ContentsSaved.Invoke("In The url:[" + _next_url + "]IMG counts:" + _count_current_URL);
 54                 _next_url = GetNextHtmlUrl(_html);
 55
 56             }
 57
 58
 59             DialogResult dlresult = MessageBox.Show("fund image:" + feedList.Count, "ALL search result was prased and saveD in ./URLCollection.txt.\nContinue download?", MessageBoxButtons.YesNo);
 60             switch (dlresult)
 61             {
 62                 case DialogResult.Yes:
 63                     {
 64                         SaveURLBuffer(_savePath + "URLCollection.txt");
 65                         mThreadManager.DispatchWork();
 66                         break;
 67                     }
 68                 case DialogResult.No:
 69                     {
 70                         SaveURLBuffer(_savePath + "URLCollection.txt");
 71                         break;
 72                     }
 73             }
 74             //增加显示状态栏
 75         }
 76
 77         /// <summary>
 78         /// stop work
 79         /// </summary>
 80         public void Abort()
 81         {
 82             if (mThreadManager != null)
 83             {
 84                 mThreadManager.StopWorking();
 85             }
 86         }
 87
 88         /// <summary>
 89         /// save the imgages url to local
 90         /// </summary>
 91         /// <param name="filepath"></param>
 92         public void SaveURLBuffer(string filepath)
 93         {
 94             FileStream fs = new FileStream(filepath, FileMode.Create, FileAccess.ReadWrite);
 95             StreamWriter sw = new StreamWriter(fs);
 96             foreach (var i in feedList)
 97                 sw.WriteLine(i.imgSrc);
 98             sw.Flush();
 99             sw.Close();
100             fs.Close();
101         }
102
103         #region   网页请求方法
104
105         /// <summary>
106         /// downloaad image in (index) work thread
107         /// </summary>
108         /// <param name="index"></param>
109         private void GetIMGDownload(int index)
110         {
111             string imgUrl = "";
112             try
113             {
114                 lock (_locker)// lock  feedlist  access
115                 {
116                     if (feedList.Count <= 0)
117                     {
118                         mThreadManager.FinishWoking(index);
119                         if (mThreadManager.IsAllFinished())
120                             DownloadFinish(index);
121                         return;
122                     }
123                     imgUrl = feedList.First().imgSrc;
124                     feedList.RemoveAt(0);
125                 }
126                 string fileName = imgUrl.Substring(imgUrl.LastIndexOf("/") + 1);
127                 WebClient wbc = new WebClient();
128                 wbc.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadFileCallback);
129                 wbc.DownloadFileAsync(new Uri(imgUrl), _savePath + fileName,fileName+"in task:"+index);
130             }
131             catch (WebException we)
132             {
133                 System.Windows.Forms.MessageBox.Show("RequestImageFAIL" + we.Message + imgUrl + we.Status);
134             }
135         }
136
137         /// <summary>
138         /// call this when the img save finished
139         /// </summary>
140         /// <param name="sender"></param>
141         /// <param name="e"></param>
142         private void DownloadFileCallback(object sender, AsyncCompletedEventArgs e)
143         {
144             if (e.Error != null)
145             { //下载成功
146                // WebClient wbc=sender as WebClient;
147              //   wbc.Dispose();
148                 if(ContentsSaved!=null)
149                     ContentsSaved((string)sender);
150                 string msg=sender as string;
151                 mThreadManager.FinishWoking((int)msg[msg.Length-1]);
152                 mThreadManager.DispatchWork();
153             }
154             throw new NotImplementedException();//下载完成回调;
155         }
156
157         /// <summary>
158         /// get response html string
159         /// </summary>
160         /// <param name="wbUrl"></param>
161         /// <param name="heardCookie"></param>
162         /// <returns></returns>
163         public string GetHtmlDownload(string wbUrl, string heardCookie)
164         {
165             string url = wbUrl;
166             string Cookie = heardCookie;
167             string html = null;
168             WebClient client = new WebClient();
169             client.Encoding = System.Text.ASCIIEncoding.UTF8;
170             client.Headers.Add("Cookie", Cookie);
171
172             Stream data = client.OpenRead(url);
173
174             StreamReader reader = new StreamReader(data);
175             html = reader.ReadToEnd();
176             client.Dispose();
177             return html;
178         }
179
180         /// <summary>
181         /// prase html string return the picture url number in this page
182         /// </summary>
183         /// <param name="html"></param>
184         /// <returns></returns>
185         public int GetHtmlPrased(string html)
186         {
187             string _html = html;
188             string result;
189             int count=0;
190             Regex regex = new Regex(@"(?<=http)[^""]+(?=jpg)");
191             MatchCollection theMatches = regex.Matches(_html);
192             foreach (Match thematch in theMatches)
193             {
194                 if (thematch.Length != 0)
195                 {
196                     result = "http" + thematch.Value.Replace("\\", "") + "jpg";
197
198                     //TO DO : 定义匹配规则查找相同的微博。
199
200                     feedList.Add(new WB_Feed(result));
201                     count++;
202                 }
203             }
204             return count;
205         }
206
207         /// <summary>
208         /// form the url commond to get next page
209         /// </summary>
210         /// <param name="url"></param>
211         /// <param name="num"></param>
212         /// <returns></returns>
213         public string GetNextHtmlUrlFromPageNUM(string url,int num)
214         {
215             string nextPage;
216             string preUrl = url;
217             int pageIdex = preUrl.IndexOf("page")+5;
218             nextPage=preUrl.Remove(pageIdex, 1);
219             nextPage = nextPage.Insert(pageIdex, "" + num);
220             return nextPage;
221         }
222         /// <summary>
223         /// prase html string to get the next page url
224         /// </summary>
225         /// <param name="html"></param>
226         /// <returns></returns>
227         public string GetNextHtmlUrl(string html)
228         {
229             string nextPage;
230             string s_domain;
231             string _html = html;
232
233             int nextIndex = _html.LastIndexOf("page next");//find last to be fast
234             if (nextIndex < 0)
235             {
236
237                 MessageBox.Show("there is not nextpage");
238                 return null;
239             }
240             //MessageBox.Show("find next in=" + nextIndex);
241             int herfIndex = _html.LastIndexOf("href=", nextIndex);
242             nextPage = _html.Substring(herfIndex + 5 + 2, nextIndex - herfIndex);
243             nextPage= nextPage.Substring(0, nextPage.IndexOf(@"""") - 1);
244             nextPage= nextPage.Replace("\\", "");
245             //$CONFIG['s_domain'] = 'http://s.weibo.com';
246             int domainIndex=html.IndexOf("'s_domain'");
247             domainIndex = html.IndexOf('=', domainIndex)+3;
248             int domainLength=html.IndexOf(";",domainIndex)-1-domainIndex;
249             s_domain = html.Substring(domainIndex, domainLength);
250
251             nextPage = s_domain + nextPage;
252             return nextPage;
253         }
254         #endregion
255
256
257
258         /// <summary>
259         /// work group manageer of downloading images  with defult 4 work thread;
260         /// </summary>
261         private class ThreadManager
262         {
263             private bool[] _reqBusy = null; //每个元素代表一个工作实例是否正在工作
264             private int _reqCount = 4; //工作实例的数量
265             private bool _stop = true;
266             public delegate void Do_a_Work_Handler(int index);
267             public  Do_a_Work_Handler dowork_handler;
268             public ThreadManager(int threadCount)
269             {
270                 _reqCount = threadCount;
271                 _reqBusy = new bool[threadCount];
272                 for (int i=0;i<threadCount;i++)
273                 {
274                     _reqBusy[i] = false;
275                 }
276                 _stop = false;
277             }
278             public void StartWorking(int index)
279             {
280                 _reqBusy[index] = true;
281                 dowork_handler.Invoke(index);/////invoke requeset resource
282             }
283             public void FinishWoking(int index)
284             {
285                 _reqBusy[index] = false;
286             }
287             public bool IsAllFinished()
288             {
289                 bool done = true;
290                 foreach (var i in _reqBusy)
291                     done = i & done;
292                 return done;
293             }
294             public void WaitALLFinished()
295             {
296                 while (!IsAllFinished())
297                     Thread.Sleep(1000);
298             }
299             public void StopWorking()
300             {
301                 _stop = true;
302                 for (int i = 0; i < _reqCount; i++)
303                     _reqBusy[i] = false;
304             }
305             public void DispatchWork()
306             {
307                 if (_stop)
308                     return;
309                 for (int i = 0; i < _reqCount; i++)////判断i编号的工作实例是否空闲
310                     if (!_reqBusy[i])
311                         StartWorking(i);
312             }
313         }
314     }
315
316     /// <summary>
317     /// the class of weibo data  you can add more field for get more detail in codes
318     /// </summary>
319     public class WB_Feed
320     {
321         public WB_Feed(string img)
322         {
323             imgSrc = img;
324         }
325         public string imgSrc { get; set; }
326
327     }
328
329 }

主要代码

转载于:https://www.cnblogs.com/qingfengyiqu/p/4381623.html

怎么编写微博爬虫 图片爬虫相关推荐

  1. python爬虫图片工具安卓版下载_python图片爬虫(图片爬虫工具) 1.1绿色版

    python图片爬虫(图片爬虫工具)是一款专门为互联.it行业的小伙伴们打造的爬虫工具,可以帮大家对软件进行优化.seo的人一定会用的上哦,有兴趣的赶紧下载了哦!python图片爬虫代码如下: #-* ...

  2. python爬虫微博评论图片_python爬虫爬取微博评论

    原标题:python爬虫爬取微博评论 python爬虫是程序员们一定会掌握的知识,练习python爬虫时,很多人会选择爬取微博练手.python爬虫微博根据微博存在于不同媒介上,所爬取的难度有差异,无 ...

  3. 函数计算+云市场实现手机号归属地和图片爬虫系统设计...

    很荣幸今天能邀请大家来参加阿里云2018年的MVP的动手实践活动,今天小编带着大家完成两个动手实践活动,通过两个简单实用的例子来演示无服务器架构的真正魅力,case1:通过函数计算+Http触发器+云 ...

  4. Node学习记录: 图片爬虫

    一 const request = require('request'); request 对http进行封装的npm request(url,(err,req)=>{ let body=req ...

  5. [python 爬虫]Python爬虫抓取虎扑论坛帖子图片

    自从可以实现抓取文字了,自然要尝试更多的类型,比如图片.我是一个有逛虎扑论坛习惯的人,经常会发现有些帖子的图片挺好看的想保存下来,但是如果人为保存的话,一个帖子至少都有二三十张,这将是一个庞大的工作量 ...

  6. java爬虫编写步骤_JAVA爬虫--编写第一个网络爬虫程序

    JAVA爬虫–编写第一个网络爬虫程序 前言上一章节介绍了XPATH基础语法,本章节将手把手带大家编写第一个爬虫程序,同时也希望能通过这个爬虫程序,帮助大家熟悉上一章节学习的XPATH基础语法并运用到实 ...

  7. 教你如何快速实现一个图片爬虫

    什么是爬虫? 如果是没有接触过爬虫的人可能会有些许疑惑,爬虫是个什么东西呢?其实爬虫的概念很简单,在互联网时代,万维网已然是大量信息的载体,如何有效地利用并提取这些信息是一个巨大的挑战.当我们使用浏览 ...

  8. 用云函数快速实现图片爬虫

    本文会跟大家介绍,如何在本地使用知晓云云函数 API 与 cheerio 开发一个图片爬虫,并使用 webpack 与 mincloud 将代码打包并上传部署到知晓云. 技术栈: 代码打包工具:web ...

  9. go写的图片爬虫,支持单页以及列表

    golang版本的图片爬虫,效果如下 github链接地址:https://github.com/lengyue1084/sspider 里面有可执行文件,使用了go的协程以及一些特性,新手可以拿来学 ...

  10. python如何爬取图片到指定文件夹论文_基于Python的图片爬虫程序设计

    互联网中包含大量有价值的 数据,网络爬虫通过既定规则可 以自动地抓取互联网数据并下载 至本地存储.研究网络爬虫的工 作原理和基于 Python 网络信息爬 取技术模块功能,基于 Requests- B ...

最新文章

  1. 3 calender python_python3笔记二十一:时间操作datetime和calendar
  2. IDEA如何将项目中文件夹设置为Sources(蓝色)
  3. 整型数组中三个数的最大乘积
  4. 安卓 spinner下拉框 做模糊查询_想做短视频不知道用什么工具?11个免费制作工具收藏起来...
  5. Setup Factory打包时实现第三方DLL文件的注册
  6. 【ArcGIS风暴】ArcGIS栅格数据(分区)统计方法总结
  7. 小米摄像头有onvif协议_监控摄像头完好但图像不行,肯定逃不过这10个问题
  8. postgreSQL源码分析——索引的建立与使用——GIN索引(3)
  9. wincc工程组态论文_基于WinCC软件的组态设计与实现
  10. 物联网核心安全系列——物联网安全需求
  11. 从零基础入门Tensorflow2.0 ----四、12. tf_data基础api使用
  12. vue 下载文档乱码
  13. halcon之屌炸天的自标定(1)
  14. Centos7重置用户密码
  15. Web.xml 错误或异常页面配置
  16. layui数据表格重载与导出
  17. thinkpad X1catbon2019款装系统时无法U盘启动解决办法
  18. 【实战篇】37 # 如何使用 QCharts 图表库绘制常用数据图表?
  19. 由椭圆一般方程求解椭圆标准方程参数
  20. 海奥华预言--第七章 慕大陆和远东岛

热门文章

  1. 谷歌seo基础:看完就能上手操作的优化方案
  2. 摘抄笔记 centos内核优化
  3. 特教学校计算机课,北京特教学校引入编程课 计算机语言为听障孩子打开一扇智能之门...
  4. PS2022神经滤镜Neural Filters离线安装包(PS2022/PS2021)
  5. 三层交换机和vrrp协议
  6. excel双击打不开,但是点击文件里的打开就行
  7. 如何求地球上两点之间的最短距离_高中数学“最实在”的蒙题技巧,让高中数学短时间内突破120分...
  8. Jmeter 使用详解、性能压测分析与性能优化思路
  9. 难得一见的数据库事务异常 Deadlock found when trying to get lock解决办法dao.DeadlockLoserDataAccessException怎么办
  10. android 微博功能实现,android 新浪微博实现分享功能