今天,写了个小代码。抓取首页中的极客头条。效果如图:

分享给新手朋友。
要点:
1. 使用Apache HttpClient库实现GET请求。
2. 异步请求处理。
3. 正则表达式抓取自己需要的数据。
1. 使用Apache HttpClient库实现GET请求。
使用Apache只需简单三步

HttpClient httpClient = new DefaultHttpClient();  //创建一个HttpClientHttpGet httpGet = new HttpGet(“http://www.csdn.net/”); //创建一个GET请求HttpResponse response = httpClient.execute(httpGet); //发送GET请求,并响应内容
2. 异步请求处理。
异步请求的实现也很简单,开辟新线程执行请求处理,请求完成通过Handler在主线程处理所获得的数据。具体看代码。
3. 正则表达式抓取自己需要的数据。
这个更简单,我推荐一个工具RegexTester,使用方法在相关文档。
我这里说下,就算你什么正则表达式一点都不知道,你只要知道(.*?)就可以了。它可以让你抓取基本上所有你需要的数据。
".*?"注意是三个字符一起,代表贪婪匹配任意数量的任意字符。可以简单的理解为任何字符。
如"a.*?b"对字符串"eabcd",进行匹配,将找到"abcd",其中".*?"匹配"bc"。
我们需要抓取的内容一般用"(.*?)"表示,注意这里是包含括号的。这很重要,用括号表示我们要提取的内容。
我们具体分析CSDN首页源代码,下面每步操作都应该在RegexTester测试进行。
很容易找到,我们要抓取内容的毎一条是如下格式。

  • 宇宙员在太空中如何洗澡、睡觉、上厕所?
  • 我们要抓取的内容是标题 和 URL地址。都用(.*?)代替
  • \1
  • 对比上面,我们要抓取的内容都用(.*?)代替,这里“\1 ”是代表第一个(.*?)的内容。他们是重复内容。
    同理如果我们用“\2”将代表与第二个括号相同内容。这里我们没有使用。
    用工具测试通过,发现没问题,能找出。
    再简化,我们删去一些对定位无关紧要的内容,这步简化要测试,保证匹配内容同上。
    title="(.*?)" href="(.*?)" target="_blank" οnclick="LogClickCount(this,363)
    我们发现target="_blank" οnclick="LogClickCount(this,在其他地方也有,是不能区分的内容的匹配词,我们用.*?忽略。注意,不用括号,用括号是我们提取的内容。最后我们得到一个特征字串,通过下面特征字串可以在源码众多的字符中,
    提取我们要的内容。
    title="(.*?)" href="(.*?)".*?363
    注意如上内容要在作为代码字符串,要经过一点处理,在每个"引号前加“\",
    "title=\"(.*?)\" href=\"(.*?)\".*?363"
    在代码中是一段很短的代码:
    Pattern p = Pattern.compile("title=\"(.*?)\" href=\"(.*?)\".*?363");Matcher m = p.matcher(csdnString); //csdn首页的源代码字符串while (m.find()) { //循环查找匹配字串    MatchResult mr=m.toMatchResult();    Map map = new HashMap();    map.put("title", mr.group(1));//找到后group(1)是表达式第一个括号的内容    map.put("url", mr.group(2));//group(2)是表达式第二个括号的内容    result.add(map);}
    具体代码如下:
    public class MainActivity extends ListActivity {ListView listview;Handler handler;List> data;final String CSDNURL = "http://www.csdn.net/";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        handler = getHandler();        ThreadStart();    }    /**     * 新开辟线程处理联网操作     * @author Lai Huan     * @created 2013-6-20     */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();}/** * 联网获得数据 * @return 数据 * @author Lai Huan * @created 2013-6-20 */private List> getCsdnNetDate() {List> result = new ArrayList>();String csdnString = http_get(CSDNURL);//
  • \1
  • //title="(.*?)" href="(.*?)".*?,363\)Pattern p = Pattern.compile("title=\"(.*?)\" href=\"(.*?)\".*?363");Matcher m = p.matcher(csdnString);while (m.find()) {MatchResult mr=m.toMatchResult();Map map = new HashMap();map.put("title", mr.group(1));map.put("url", mr.group(2));result.add(map);}return result;}/** * 处理联网结果,显示在listview * @return * @author Lai Huan * @created 2013-6-20 */private Handler getHandler() { return new Handler(){public void handleMessage(Message msg) {if (msg.what < 0) {Toast.makeText(MainActivity.this, "数据获取失败", Toast.LENGTH_SHORT).show();}else {initListview();}} };}/** * 在listview里显示数据 * @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() {@Overridepublic void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {Map 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 请求网址 * @return 网页内容的字符串 * @author Lai Huan * @created 2013-6-20 */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编码转化为字符串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();//设定连接超时和读取超时时间HttpConnectionParams.setConnectionTimeout(httpParams, 6000);HttpConnectionParams.setSoTimeout(httpParams, 30000);return new DefaultHttpClient(httpParams);}}
    相关文档:
    正则表达式30分钟入门教程 http://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html

    更多相关文章

    1. Android控件之AutoCompleteTextView(自动匹配输入的内容)
    2. Android模拟器镜像介绍
    3. Android网络通信库Volley简介(Google IO 2013)
    4. Android设备上使用WiFinspect抓取网络通讯包
    5. Android控件之HorizontalScrollView 去掉滚动条
    6. Android(安卓)Rxjava和retrofit
    7. 判断Http请求由手机端发起,还是有电脑端发起
    8. Android中关于Volley的使用(三)认识 CacheDispatcher
    9. Android(安卓)控件备用收集

    随机推荐

    1. Android根据Data匹配隐式Intent的实例
    2. android使用http协议实现文件的上传
    3. library里面使用butterknife的正确姿势(an
    4. android OpenGL ES 2.0
    5. android 数据库操作异常
    6. 如何打包Android(安卓)Wearable 应用程序
    7. 第三章 Libgdx必备工具
    8. Android(安卓)studio 升级3.1.2, 运行之前
    9. Android零散收集
    10. 安卓学习笔记(一)搭建安装开发环境(android