网络爬虫爬取数据 本地数据库储存 远程api分析 模型
2016-11-19 16:00
507 查看
序言
20161119 写本次项目工程:
第一部分:https://github.com/RenjiaLu9527/WebMagic_test-20161119—mysq
第二部分:https://github.com/RenjiaLu9527/JFreeChart-20161119/
相关博客、论坛网站链接如下
WebMagic简单灵活的爬虫框架。http://webmagic.io
WebCollector JAVA爬虫框架 http://www.oschina.net/p/webcollector?fromerr=WSgeV8m4
给推荐几个github上优秀的java爬虫项目?【知乎】
83款 网络爬虫开源软件
利用WebMagic的Cookie机制进行页面爬取
DwyaneWade NBA球星德维恩·韦德 的新浪微博
java实现各种数据统计图(柱形图,饼图,折线图)
JFreechart 1.0.19开源包下载链接
一键将正则表达式转换为JAVA python等语言的字符串:
正则表达式测试工具/常用正则表达式/正则代码生成 - 在线工具
一个星期多一点,在众多的爬虫框架中选择了Webmagic,WebMagic简单灵活的爬虫框架。
简单易用,在这之前用的是WebCollector JAVA爬虫框架,它的模块划分弄了一天也没搞清楚,文档没有webmagic的全,上手太慢,所以放弃
webmagic是国人做的,目前我使用的功能很少,对其框架的扩展定制内容很少,感觉不出什么优点来,基本功能使用上手很快
正文
有个概念:分布式:一个业务分拆多个子业务,部署在不同的服务器上
集群:同一个业务,部署在多个服务器上
爬虫可以做很多事,将网络上感兴趣的资源通过爬虫大规模的抓取,然后进行分析等其他操作,可以做出很多有意思的东西,比如‘舆情分析系统’‘网络环境文明用语情况分析’还可以‘爬取某个网站的图片、文字、视频’相当于一键直接下载,非常方便;
我做的这个小模型是
webmagic框架爬虫抓取某位微博用户的每条微博
下载保存本地并储存到本地数据库Mysql
调用Watson的Tone Analyzer API逐条分析本地数据库的数据并收集分析Json结果
用JAVA GUI显示情感变化趋势
四部分,
前两部分由于微博网站页面的显示方式是由 JSP 函数获取显示的,导致webmagic的xpath和css无法正常使用,还有他的正则表达式解析也不正常;最后不得不放弃这三个函数,老老实实的用java自带的正则解析函数才解析正常,
要点
1 大概了解网页的构成2 webmagic熟悉基本用法(官网文档很详细)
3 JDBC等连接数据库的操作 和数据库的基本使用
4 正这表达式(重点!好好研究)
5 还是 get/post方法 和 Json解析
6 学会调用开源库 开源模板,比如这个折线图开源包
先分析网页的构成 然后再测试抓取是否成功。
这里我以 DwyaneWade NBA球星德维恩·韦德的微博为例 抓取
我将第一第二步建了一个工程 webmagic_test,第三第四步也建立一个工程JFreeChart;两个工程分开运行
webmagic_test工程目录如下
JFreeChart工程目录如下
笔记
webmagic框架的两个java文件SinaBlogProcessor.java****OneFilePipeline.java
代码如下:
SinaBlogProcessor.java
package main; import java.io.File; import java.io.FileNotFoundException; import java.io.UnsupportedEncodingException; import us.codecraft.webmagic.downloader.Downloader; import java.util.ArrayList; import java.util.List; import us.codecraft.webmagic.Page; import us.codecraft.webmagic.Site; import us.codecraft.webmagic.Spider; import us.codecraft.webmagic.Task; import us.codecraft.webmagic.pipeline.FilePipeline; import us.codecraft.webmagic.pipeline.Pipeline; import us.codecraft.webmagic.processor.PageProcessor; /** * @author code4crafter@gmail.com <br> */ public class SinaBlogProcessor implements PageProcessor { public static String PATHNAME = "H:/php/wamp/wamp/www/_webmagicdata/weibodata_jdbc/jdbc_weibodata_page"; private static long userNum = 0; private static String userId = ""; private Site siteold = Site.me().setSleepTime(3000);// .setUserAgent( // "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like // Gecko) Chrome/45.0.2454.101 Safari/537.36"); private volatile static int maini = 0; private Site site = new Site().setRetryTimes(3).setSleepTime(2000).setTimeOut(10000) // 添加cookie之前一定要先设置主机地址,否则cookie信息不生效 .setDomain(".weibo.com") // 添加抓包获取的cookie信息(某些网站如果没有设定cookice无法访问) .addCookie("Apache", "6047605616040.527.1448080352314") /*如何添加 cookice:[http://blog.csdn.net/kingsonyoung/article/details/51753639] */ // 添加请求头,有些网站会根据请求头判断该请求是由浏览器发起还是由爬虫发起的 .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.245") .addHeader("Accept", "*/*").addHeader("Accept-Encoding", "gzip, deflate, sdch") .addHeader("Accept-Language", "zh-CN,zh;q=0.8").addHeader("Connection", "keep-alive").addHeader("Referer", "http://weibo.com/p/1003062264358493/home?is_search=0&visible=0&is_all=1&is_tag=0&profile_ftype=1&page=1#feedtop"); @Override public void process(Page page) { String str = "" + page.getUrl().toString(); // System.out.println("#1"); if (str.indexOf("#feedtop") >= 0) { // System.out.println("#2"); if (page.getHtml().toString().indexOf("抱歉,你访问的页面地址有误,或者该页面不存在") < 0 && page.getHtml().toString().indexOf("请检查输入的网址是否正确") < 0 && page.getHtml().toString().i f7df ndexOf("网络繁忙") < 0 && page.getHtml().toString().indexOf("请稍后再试") < 0) { // System.out.println("#3"); str = str.substring(0, str.indexOf("#feedtop")); str = str.substring(str.indexOf("&page=") + 6, str.length()); int cnt = 0; int pagenum = Integer.parseInt(str); System.out.println("pagenum=" + pagenum); // 获取页数 String xialaURL1 = "http://weibo.com/p/aj/v6/mblog/mbloglist?ajwvr=6&domain=100505&is_search=0&visible=0&is_all=1&is_tag=0&profile_ftype=1" + "&page=" + pagenum + "&pagebar=0" + "&pl_name=Pl_Official_MyProfileFeed__23&id=" + userId + "&script_uri=/p/" + userId + "/home&feed_type=0" + "&pre_page=" + pagenum + "&domain_op=100505&__rnd=1479123380183"; String xialaURL2 = "http://weibo.com/p/aj/v6/mblog/mbloglist?ajwvr=6&domain=100505&is_search=0&visible=0&is_all=1&is_tag=0&profile_ftype=1" + "&page=" + pagenum + "&pagebar=1" + "&pl_name=Pl_Official_MyProfileFeed__23&id=" + userId + "&script_uri=/p/" + userId + "/home&feed_type=0" + "&pre_page=" + pagenum + "&domain_op=100505&__rnd=1479123380183"; List<String> listurl = new ArrayList<String>(); listurl.add(xialaURL1); listurl.add(xialaURL2); page.addTargetRequests(listurl); page.putField("[Chushiyemian]", page.getHtml()); } else { System.out.println("userId=" + userId + "页面不存在 404"); // userId++; maini = -1; } } else { // 两个下拉刷新页面 page.putField("[Xialashuaxin]", page.getJson()); if (page.getJson().toString().indexOf("WB_feed_detail clearfix") < 0) { maini = -1; System.out.println("userId=" + userId + "到达最后一页"); } } } @Override public Site getSite() { return site; } public static void main(String[] args) { // http://weibo.com/p/1005055317970558/home? // http://weibo.com/kevindurant?is_search=0&visible=0&is_all=1&is_tag=0&profile_ftype=1&page=2#feedtop // http://weibo.com/p/1003061735538085/home?from=page_100306_profile&wvr=6&mod=data&is_all=1#place for (userNum = 93; userNum < 99; userNum++) { userId = "10030622643584" + userNum; PATHNAME = "H:/php/wamp/wamp/www/_webmagicdata/weibodata_jdbc/" + userId + "jdbc_weibodata_page"; OneFilePipeline.cnt = 0;// 置0 String pageURLs = "http://weibo.com/p/" + userId + "/home?is_search=0&visible=0&is_all=1&is_tag=0&profile_ftype=1&page=";// 1#feedtop"; String pageURLe = "#feedtop"; String xialaPagebars = ""; for (maini = 1; maini <= 999 && maini > 0; maini++) { try { Spider.create(new SinaBlogProcessor()) // .addUrl("http://weibo.com/languageexchange?refer_flag=1001030201_&is_all=1") // .addPipeline(new // FilePipeline("H:/php/wamp/wamp/www/_webmagicdata")) .addPipeline(new OneFilePipeline(PATHNAME)).addUrl(pageURLs + maini + pageURLe).thread(50) .run(); } catch (FileNotFoundException | UnsupportedEncodingException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } System.out.println("userId=" + userId + "处理完毕/n传送至watson分析并返回显示"); } } // @Override // public void process(ResultItems arg0, Task arg1) { // // TODO 自动生成的方法存根 // System.out.println("process 2参数函数"+arg0.get("content1")); // // }1005053610038332 }
注意添加 cookice才能正常访问微博,每个人的不同,此处不贴出来了
OneFilePipeline.java
package main; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import us.codecraft.webmagic.ResultItems; import us.codecraft.webmagic.Task; import us.codecraft.webmagic.pipeline.Pipeline; import us.codecraft.webmagic.utils.FilePersistentBase; import utils.Jdbc; import java.io.*; import java.util.Map; /** * @author code4crafer@gmail.com */ public class OneFilePipeline extends FilePersistentBase implements Pipeline { public static int cnt = 0; private Logger logger = LoggerFactory.getLogger(getClass()); private PrintWriter printWriter; /** * create a FilePipeline with default path"/data/webmagic/" */ public OneFilePipeline() throws FileNotFoundException, UnsupportedEncodingException { this("/data/webmagic/"); // this("H:\php\wamp\wamp\www/_webmagicdata/"); } public OneFilePipeline(String path) throws FileNotFoundException, UnsupportedEncodingException { setPath(path); printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(getFile(path)), "UTF-8")); } @Override public synchronized void process(ResultItems resultItems, Task task) { printWriter.println("url:\t" + resultItems.getRequest().getUrl()); for (Map.Entry<String, Object> entry : resultItems.getAll().entrySet()) { if (entry.getValue() instanceof Iterable) { Iterable value = (Iterable) entry.getValue(); printWriter.println(entry.getKey() + ":"); for (Object o : value) { printWriter.println(o); } } else { new Jdbc(); printWriter.println(entry.getKey() + ":\t" + entry.getValue()); // 先保存 再处理本地 Jdbc.saveToMysql(Jdbc.parseData(entry.getValue())); } } printWriter.flush(); } @Override public java.io.File getFile(java.lang.String fullName) { cnt++; System.out.println("fullname=" + fullName + cnt); return new File(fullName + cnt); } }
模块划分很清楚,不多说
一段很长的正则:
//////////////////////////////////////////////////////////////////////
1 获取 正常微博文字
网页代码
<div class=\"WB_text W_f14\" node-type=\"feed_list_content\" nick-name=\"DwyaneWade\">\n Game day! - 比赛日! <\/div>
正则表达式
(?<=(<div\Wclass=\\"WB_text\WW_f14\\"\Wnode-type=\\"feed_list_content\\"\Wnick-name=\\"\w+\\">\\n)).*?(?=<(\\\/div>))
2 转发别人的微博时,没有nick-name=\”DwyaneWade\”
网页代码
<div class=\"WB_text W_f14\" node-type=\"feed_list_content\" >\n Single Days, end today. 脱单,就在今天。<a target=\"_blank\" render=\"ext\" suda-uatrack=\"key=topic_click&value=click_topic\" class=\"a_topic\" extra-data=\"type=topic\" href="http://weibo.com/p/1003062264358493/\""http:\/\/huati.weibo.com\/k\/%E5%93%88%E5%95%A4%E8%81%94%E7%9B%9F?from=501\">#哈啤联盟#<\/a> <\/div>\n
正则表达式
(?<=(<div\Wclass=\\"WB_text\WW_f14\\"\Wnode-type=\\"feed_list_content\\"\W((>\\\w)|(.{10}\\"\w{0,50}\\">\\n)))).*?(?=<(\\\/div>)) //////////////////////////////////////////////
Java String表示
"(?<=(<div\\Wclass=\\\\\"WB_text\\WW_f14\\\\\"\\Wnode-type=\\\\\"feed_list_content\\\\\"\\W((>\\\\\\w)|(.{10}\\\\\"\\w{0,50}\\\\\">\\\\n)))).*?(?=<(\\\\\\/div>))"
这么长的正则效率可能略低,但提升了代码整洁度,而且由于xpath css无法使用,没办法的办法
注意
log4j.properties文件,webmagic调用了什么必须有这个文件包含才能显示log日志
# Configure logging for testing: optionally with log file log4j.rootLogger=WARN, stdout # log4j.rootLogger=WARN, stdout, logfile log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n log4j.appender.logfile=org.apache.log4j.FileAppender log4j.appender.logfile.File=target/spring.log log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
end
略累
睡觉
20161119JJ401 16:24
相关文章推荐
- 《网络爬虫-Python和数据分析》数据库建库建表问题
- 网络附加存储设备NAS等设备应用在数据备份(本地及远程数据备份)、数据容灾应用中的分析
- 从远程数据库复制全部数据到本地数据库
- 用SQL语句将远程SQL Server数据库中表数据导入到本地数据库相应的表中
- sql server 2008 把远程的数据库的数据转移到本地数据数据库里
- 大数据时代:基于微软案例数据库数据挖掘知识点总结(Microsoft 神经网络分析算法原理篇)
- 将MSSQL数据库文件从本地机迁移到远程服务器(包括主键、默认值、表内数据)
- 数据仓库数据库设计方法---关系模型和多维模型比较分析
- 定时从远程的数据库中取数据,然后把取出来的数据插入或更新本地的oracle数据库的表
- Oracle数据泵远程导入文件到本地数据库
- 将远程SQL Server 数据库中表数据导入本地数据库相应的表
- (原创)大数据时代:基于微软案例数据库数据挖掘知识点总结(Microsoft 神经网络分析算法原理篇)
- sqlserver2005 远程服务器数据 完全拷贝 到本地数据库
- 将远程SQL Server 数据库中表数据导入本地数据库相应的表
- 利用数据泵导出远程数据到本地数据库!!!
- 用Python进行网络爬虫和数据分析的初次尝试(一)
- 用SQL语句将远程SQL Server数据库中表数据导入到本地数据库相应的表中
- 如何把本地的数据库,导入到远程的数据库呢? 如何把本地的数据库中的表的结构和数据库里面的数据传过去呢?数据库的一些版本号
- 用SQL语句将远程SQL Server数据库中表数据导入到本地数据库相应的表中
- 从远程Sql Server 2005服务器中导出数据到本地(本地数据库版本:Sql Server 2005)