Android抓取CSDN首頁極客頭條內(nèi)容完整實例
今天,寫了個小代碼。抓取首頁中的極客頭條。效果如圖:

分享給新手朋友。
要點:
1.使用ApacheHttpClient庫實現(xiàn)GET請求。
2.異步請求處理。
3.正則表達式抓取自己需要的數(shù)據(jù)。
1.使用ApacheHttpClient庫實現(xiàn)GET請求。
使用Apache只需簡單三步
HttpClient httpClient = new DefaultHttpClient(); //創(chuàng)建一個HttpClient HttpGet httpGet = new HttpGet(“http://www.csdn.net/”); //創(chuàng)建一個GET請求 HttpResponse response = httpClient.execute(httpGet); //發(fā)送GET請求,并響應(yīng)內(nèi)容
2.異步請求處理。
異步請求的實現(xiàn)也很簡單,開辟新線程執(zhí)行請求處理,請求完成通過Handler在主線程處理所獲得的數(shù)據(jù)。具體看代碼。
3.正則表達式抓取自己需要的數(shù)據(jù)。
這個更簡單,我推薦一個工具RegexTester,使用方法在相關(guān)文檔。
我這里說下,就算你什么正則表達式一點都不知道,你只要知道(.*?)就可以了。它可以讓你抓取基本上所有你需要的數(shù)據(jù)。
".*?"注意是三個字符一起,代表貪婪匹配任意數(shù)量的任意字符??梢院唵蔚睦斫鉃槿魏巫址?。
如"a.*?b"對字符串"eabcd",進行匹配,將找到"abcd",其中".*?"匹配"bc"。
我們需要抓取的內(nèi)容一般用"(.*?)"表示,注意這里是包含括號的。這很重要,用括號表示我們要提取的內(nèi)容。
我們具體分析CSDN首頁源代碼,下面每步操作都應(yīng)該在RegexTester測試進行。
很容易找到,我們要抓取內(nèi)容的毎一條是如下格式。
<li><a title="宇宙員在太空中如何洗澡、睡覺、上廁所?" rel="external nofollow" target="_blank" onclick="LogClickCount(this,363);">宇宙員在太空中如何洗澡、睡覺、上廁所?</a></li>
我們要抓取的內(nèi)容是標題 和 URL地址。都用(.*?)代替
<li><a title="(.*?)" href="(.*?)" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" target="_blank" onclick="LogClickCount(this,363);">\1</a></li>
對比上面,我們要抓取的內(nèi)容都用(.*?)代替,這里“\1”是代表第一個(.*?)的內(nèi)容。他們是重復(fù)內(nèi)容。
同理如果我們用“\2”將代表與第二個括號相同內(nèi)容。這里我們沒有使用。
用工具測試通過,發(fā)現(xiàn)沒問題,能找出。
再簡化,我們刪去一些對定位無關(guān)緊要的內(nèi)容,這步簡化要測試,保證匹配內(nèi)容同上。
title="(.*?)" href="(.*?)" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" target="_blank" onclick="LogClickCount(this,363)
我們發(fā)現(xiàn)target="_blank"onclick="LogClickCount(this,在其他地方也有,是不能區(qū)分的內(nèi)容的匹配詞,我們用.*?忽略。注意,不用括號,用括號是我們提取的內(nèi)容。最后我們得到一個特征字串,通過下面特征字串可以在源碼眾多的字符中,
提取我們要的內(nèi)容。
title="(.*?)" href="(.*?)" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" .*?363
注意如上內(nèi)容要在作為代碼字符串,要經(jīng)過一點處理,在每個"引號前加“\",
"title=\"(.*?)\" href=\"(.*?)\".*?363"
在代碼中是一段很短的代碼:
Pattern p = Pattern.compile("title=\"(.*?)\" href=\"(.*?)\".*?363");
Matcher m = p.matcher(csdnString); //csdn首頁的源代碼字符串
while (m.find()) { //循環(huán)查找匹配字串
MatchResult mr=m.toMatchResult();
Map<String, Object> map = new HashMap<String, Object>();
map.put("title", mr.group(1));//找到后group(1)是表達式第一個括號的內(nèi)容
map.put("url", mr.group(2));//group(2)是表達式第二個括號的內(nèi)容
result.add(map);
}
具體代碼如下:
public class MainActivity extends ListActivity {
ListView listview;
Handler handler;
List<Map<String, Object>> data;
final String CSDNURL = "http://www.csdn.net/";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handler = getHandler();
ThreadStart();
}
/**
* 新開辟線程處理聯(lián)網(wǎng)操作
*/
private void ThreadStart() {
new Thread() {
public void run() {
Message msg = new Message();
try {
data = getCsdnNetDate();
msg.what = data.size();
}
catch (Exception e) {
e.printStackTrace();
msg.what = -1;
}
handler.sendMessage(msg);
}
}
.start();
}
/**
* 聯(lián)網(wǎng)獲得數(shù)據(jù)
* @return 數(shù)據(jù)
*/
private List<Map<String, Object>> getCsdnNetDate() {
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
String csdnString = http_get(CSDNURL);
//<li><a title="(.*?)" href="(.*?)" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" target="_blank" onclick="LogClickCountthis,363;">\1</a></li>
//title="(.*?)" href="(.*?)" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" .*?,363\)
Pattern p = Pattern.compile("title=\"(.*?)\" href=\"(.*?)\".*?363");
Matcher m = p.matcher(csdnString);
while (m.find()) {
MatchResult mr=m.toMatchResult();
Map<String, Object> map = new HashMap<String, Object>();
map.put("title", mr.group(1));
map.put("url", mr.group(2));
result.add(map);
}
return result;
}
/**
* 處理聯(lián)網(wǎng)結(jié)果,顯示在listview
* @return
*/
private Handler getHandler() {
return new Handler(){
public void handleMessage(Message msg) {
if (msg.what < 0) {
Toast.makeText(MainActivity.this, "數(shù)據(jù)獲取失敗", Toast.LENGTH_sHORT).show();
} else {
initListview();
}
}
}
;
}
/**
* 在listview里顯示數(shù)據(jù)
* @author Lai Huan
* @created 2013-6-20
*/
private void initListview() {
listview = getListView();
SimpleAdapter adapter = new SimpleAdapter(this, data,
android.R.layout.simple_list_item_1, new String[] { "title"},
new int[] { android.R.id.text1 });
listview.setAdapter(adapter);
listview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
Map<String, Object> map = data.get(arg2);
String url = (String)(map.get("url"));
Intent intent = new Intent(Intent.ACTION_VIEW);
intent .setData(Uri.parse(url));
startActivity(intent);
}
}
);
}
/**
* get請求URL,失敗時嘗試三次
* @param url 請求網(wǎng)址
* @return 網(wǎng)頁內(nèi)容的字符串
*/
private String http_get(String url) {
final int RETRY_TIME = 3;
HttpClient httpClient = null;
HttpGet httpGet = null;
String responseBody = "";
int time = 0;
do {
try {
httpClient = getHttpClient();
httpGet = new HttpGet(url);
HttpResponse response = httpClient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200) {
//用utf-8編碼轉(zhuǎn)化為字符串
byte[] bResult = EntityUtils.toByteArray(response.getEntity());
if (bResult != null) {
responseBody = new String(bResult,"utf-8");
}
}
break;
}
catch (IOException e) {
time++;
if (time < RETRY_TIME) {
try {
Thread.sleep(1000);
}
catch (InterruptedException e1) {
}
continue;
}
e.printStackTrace();
}
finally {
httpClient = null;
}
}
while (time < RETRY_TIME);
return responseBody;
}
private HttpClient getHttpClient() {
HttpParams httpParams = new BasicHttpParams();
//設(shè)定連接超時和讀取超時時間
HttpConnectionParams.setConnectionTimeout(httpParams, 6000);
HttpConnectionParams.setSoTimeout(httpParams, 30000);
return new DefaultHttpClient(httpParams);
}
}
總結(jié)
以上就是本文關(guān)于Android抓取CSDN首頁極客頭條內(nèi)容完整實例的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
相關(guān)文章
詳解Android如何設(shè)計一個全局可調(diào)用的ViewModel對象
很多時候我們需要維護一個全局可用的ViewModel,因為這樣可以維護全局同一份數(shù)據(jù)源,且方便使用協(xié)程綁定App的生命周期,那如何設(shè)計全局可用的ViewModel對象,文中介紹的非常詳細,需要的朋友可以參考下2023-05-05
Android判斷軟鍵盤彈出并隱藏的簡單完美解決方法(推薦)
下面小編就為大家?guī)硪黄狝ndroid判斷軟鍵盤彈出并隱藏的簡單完美解決方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-10-10
Android中使用socket通信實現(xiàn)消息推送的方法詳解
這篇文章主要介紹了Android中使用socket通信實現(xiàn)消息推送的方法,文中舉了一個消息發(fā)送端和一個消息接收端以及服務(wù)器端的例子來說明原理并且展示了客戶端的實現(xiàn),需要的朋友可以參考下2016-04-04
Android自定義ImageView實現(xiàn)在圖片上添加圖層效果
這篇文章給大家主要介紹了利用Android自定義ImageView如何實現(xiàn)在圖片上添加圖層的效果,實現(xiàn)的效果類似在圖片增加秒殺、搶光等標簽圖片,對大家開發(fā)的時候具有一定的參考借鑒價值,有需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧。2016-11-11
Android通知欄增加快捷開關(guān)的功能實現(xiàn)教程
對于Android來說其中一項很方便的操作便是下拉菜單,下拉菜單欄可以快捷打開某項設(shè)置,這篇文章主要給大家介紹了關(guān)于Android通知欄增加快捷開關(guān)的功能實現(xiàn),需要的朋友可以參考下2023-01-01

