天天看點

爬!扒@切#存$構%查

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