喜歡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++還将長期存在,保持強大的生命力。