最近需要從某個網頁上抓取數據。一波三折。
1. 先要找到網站頁面調用后台數據服務的url地址,但是本人對js不了解,花了不少時間在分析其網頁源代碼的js部分,試圖尋找出調用數據的鏈接。
后來得知瀏覽器都會追蹤頁面發出去的所有鏈接,chrome中,“F12->網絡” 會顯示所有的調用鏈接。讀取后端數據的鏈接就在里面。
2. 找到url鏈接之后,接下來讀取數據。
開始時用的是HttpGet類來讀取,代碼如下:
HttpGet httpGet = new HttpGet(url); CloseableHttpResponse response = null; try { response = httpClient.execute(httpGet); HttpEntity entity = response.getEntity(); body = EntityUtils.toString(entity); } catch (IOException e) { e.printStackTrace(); }
return body
但是在body中,總是會有亂碼的出現,如在頁面上顯示的“凱”在程序中顯示為亂碼。在頁面上請求頭和響應頭的內容,發現返回的字符集是“gb2312”,於是把代碼改為
body = EntityUtils.toString(entity,“gb2312”);
但是仍然顯示為亂碼。
於是在網上(http://www.qqxiuzi.cn/bianma/zifuji.php)查詢“凱”等亂碼的字符集,發現“GBK”包含這些,而“GB2312”並不包含這些比較少見的字。看來是網頁上的字符集信息不太對。
接着把代碼修改為
body = EntityUtils.toString(entity,“gbk”);
還是有問題。。。
接着嘗試在http頭中加入“charset=gbk”,沒有變化,服務端不支持。。。
3. 改為從網頁讀取字節流數據
上一步改完代碼后仍然有問題,猜測是EntityUtils內部已經做好了轉換。但是不知道怎么更進一步,所以打算從源頭開始,接收字節流數據。
代碼如下:
URL quest = new URL(url); HttpURLConnection Connection = (HttpURLConnection).quest.openConnection(); InputStream is = Connection.getInputStream(); int len = 0; byte[] temp = new byte[102400]; int llen = -1; ByteArrayOutputStream outStream = new ByteArrayOutputStream(); while ((llen = is.read(temp, 0, 102400)) != -1) { outStream.write(temp, 0, llen); } is.close(); content = new String(outStream.toByteArray(),"gbk");
用ByteArrayOutputStream接收byte數據,是為了防止中間被截斷導致最后翻譯目標字符集的時候出現錯誤。
這么使用的前提是要知道數據的字符集編碼。
從結果往回看是一個簡單的方法,但是之中的每一步都花費了不少精力才找到正確的方向,debug是個苦力活~~~
綜上,看來最有效的方法是接收字節流,自己轉成相應字符集編碼格式。