2019独角兽企业重金招聘Python工程师标准>>>
喜欢java主要是喜欢它的简单,一次调用的背后是许多开发者默默的付出,讨厌java主要是讨厌它的简单,一次调用的背后完全不知道系统私下里都干了些啥。计算机技术经历几十年发展,底层的东西日趋完善,后来人在前辈的基础上快速构建,把产品推向市场,反馈迭代再反馈再迭代,变现盈利才是王道。当下有些强业务型互联网企业重融资重逼格,满嘴设计模式数据结构算法大全,闭口不谈运营模式产品形态用户体验~!@#$%^&*()......
爬是爬虫,网页爬取,爬网页是技术活有难度有挑战,有些站点不喜欢被爬,爬烦了容易被拉黑,有些页面不是静态的,来来回回多步交互才能完成爬取,有些站点需要验证登录,各种形式验证码考验人脑眼手配合更别提机器识别了。
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>fluent-hc</artifactId>
<version>4.5.3</version>
</dependency>
String html = Executor.newInstance()
.execute(Request.Get("http://www.url.com") // 目标地址
.userAgent("Mozilla/5.0 Chrome/85.0.252.101 Safari/536.86") // 浏览器UA
.viaProxy("127.0.0.1:2017") // 代理服务
.connectTimeout(5000) // 连接超时
.socketTimeout(10000)) // 套接字超时
.returnContent() // 返回CT对象
.asString(Charset.forName("UTF-8")); // 设置字符集
扒是扒取HTML网页标签提取有价值内容,虽然每个站点都遵循html规范,但标签的定义差别还是非常大的,如果是有针对性的爬取某几家站点,可以通过配置的方式定义标签从而在元素集合中快速定位到信息。
getElementById(String id) // <h1 id="title" cid="560" docid="8168976">标题</h1>
getElementsByTag(String tag) // <a target="_blank" href="new.htm" title="财经"></a>
getElementsByClass(String class) // <div class="post"><a href="http://aaa.com"</a></div>
getElementsByAttribute(String key) // <img src="captchay?w=240&h=50" w="240" h="50"/>
getElementsByAttributeValue(String key, String value) // <span class="txt"><a target="_blank" ...
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.2</version>
</dependency>
Document doc = Jsoup.parse(htm);
Elements div = doc.getElementsByAttributeValue("class", "txt");
for(Element d : div) {
for(Element l : d.getElementsByTag("a")) {
System.out.print(l.attr("href") + " : ");
System.out.print(l.attr("title") + " : ");
System.out.println(l.text());
}
}
切是切分对中文文章或语句进行分词,每个单词由偏移、词性和词三部分构成一个item对象,所有对象构成一个集合通过迭代器可以遍历,用户可以添加自己的字典,也可以指定切分过滤策略,扩展性很不错,调用仅一行代码,返回一个容器。
<dependency>
<groupId>org.ansj</groupId>
<artifactId>ansj_seg</artifactId>
<version>5.0.0</version>
</dependency>
// 未指定策略切分
Result rst = ToAnalysis.parse(article);
// 初始化用户字典
UserDefineLibrary.insertWord("网络", "n", 1000);
// 指定词性过滤分词
FilterRecognition flt = new FilterRecognition();
flt.insertStopNatures("w");
Result rst = ToAnalysis.parse(article).recognition(flt);
存是指将数据保存起来,mongodb作为类结构化存储解决方案高效稳定分布式相当好用,对数据类型和长度没有传统关系型数据库定义时那么费劲上心,很容易就能满足入门级建库建表的要求,一般复杂性的操作都能满足,用过绝对爱不释手。
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.0.2</version>
</dependency>
GtMongo tm = new GtMongo();
Gt.TuMongoOpen("127.0.0.1",12345);
Gt.TuMongoGetDatabase("my_mongodb");
Gt.TuMongoGetCollection("my_collecttion");
Gt.TuMongoInsert(
new Document("title, "一带一路高峰时刻")
.append("url", "http://www.yidaiyilu.com")
.append("text", "一带一路”国际合作高峰论坛举行")
......
.append("keys","一带一路")
);
构是构建索引,依托elk(Elasticsearch、Logstash和Kibana)日志分析系统,特点是分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载,开源的伸缩性好,玩的好不好全看自己水平高低了。
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.1.1</version>
</dependency>
try {
String now = new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + "T" + new SimpleDateFormat("HH:mm:ss.SS+0800").format(new Date());
TransportClient tc = new PreBuiltTransportClient(Settings.EMPTY).addTransportAddress(new InetSocketTransportAddress(new InetSocketAddress(TE_HOST, TE_PORT)));
String jsn[] = {
"{\"@time\":\"" + now + "\",\"data\":{\"area\":\"area1\",\"msg\":\"msg1\",\"uid\":\"111\",\"keys\":\"key1\"}}",
"{\"@time\":\"" + now + "\",\"data\":{\"area\":\"area2\",\"msg\":\"msg2\",\"uid\":\"222\",\"keys\":\"key2\"}}",
"{\"@time\":\"" + now + "\",\"data\":{\"area\":\"area3\",\"msg\":\"msg3\",\"uid\":\"333\",\"keys\":\"key3\"}}"
};
for (int i = 0; i < jsn.length; i ++) {
IndexResponse ir = tc.prepareIndex(TE_NAME, TE_TYPE).setSource(jsn[i]).get();
System.out.println(ir.getId() + ", " + ir.getType() + ", " + ir.getIndex());
}
tc.close();
} catch (Exception e) {
e.printStackTrace();
}
查是查询,上面说了,自动发现自动创建,逻辑处理不复杂的话上手十分简单,但对中文的处理和复杂逻辑搜索还是需要花点功夫研究下的。
try {
Settings st = Settings.builder().put("cluster.name", "elasticsearch").put("node.name", "kafka").build();
TransportClient tc = new PreBuiltTransportClient(st).addTransportAddress(new InetSocketTransportAddress(new InetSocketAddress(TE_HOST, TE_PORT)));
// SearchResponse sr = tc.prepareSearch("logstash-*").get(); // 全量数据
// SearchResponse sr = tc.prepareSearch("logstash-*").setQuery(QueryBuilders.matchQuery("uid", "111")).get(); // 指定字段
// SearchResponse sr = tc.prepareSearch("logstash-*").setQuery(QueryBuilders.regexpQuery("area", ".*1")).get(); // 正则表达
// SearchResponse sr = tc.prepareSearch("logstash-*").setQuery(QueryBuilders.wildcardQuery("area", "*e*")).get(); // 通配符号
QueryBuilder qb = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("area", "area1"))
.must(QueryBuilders.regexpQuery("keys", "k.*"))
.mustNot(QueryBuilders.termQuery("uid", "xyz"));
SearchResponse sr = tc.prepareSearch("logstash-*").setQuery(qb).get();
SearchHits sh = sr.getHits();
System.out.println("共搜到: " + sh.getTotalHits() + "条结果!");
for(SearchHit ht : sh){
System.out.println(ht.getSourceAsString());
}
tc.close();
} catch (Exception e) {
System.out.println("共搜到: 0条结果!");
e.printStackTrace();
}
关于“爬!扒@切#存$构%查”的话题就这么多,抛砖引玉蜻蜓点水,总之入门十分简单,深钻还是有一定难度的。每个模块花不了几行就能实现最初级的功能,java能成为最广泛的应用开发语言确实是有它显著优势的,虽说有些开发语言随着某个领域的突破会快速发展壮大,但java和c、c++还将长期存在,保持强大的生命力。