Android抓取CSDN首页极客头条内容完整实例

作者:laihuan99 时间:2023-06-09 17:01:16 

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

Android抓取CSDN首页极客头条内容完整实例

分享给新手朋友。

要点:

1.使用ApacheHttpClient库实现GET请求。

2.异步请求处理。

3.正则表达式抓取自己需要的数据。

1.使用ApacheHttpClient库实现GET请求。

使用Apache只需简单三步


HttpClient httpClient = new DefaultHttpClient(); //创建一个HttpClient

HttpGet 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测试进行。

很容易找到,我们要抓取内容的毎一条是如下格式。


<li><a title="宇宙员在太空中如何洗澡、睡觉、上厕所?" href="http://geek.csdn.net/news/detail/1478" rel="external nofollow" target="_blank" onclick="LogClickCount(this,363);">宇宙员在太空中如何洗澡、睡觉、上厕所?</a></li>

我们要抓取的内容是标题 和 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>

对比上面,我们要抓取的内容都用(.*?)代替,这里“\1”是代表第一个(.*?)的内容。他们是重复内容。

同理如果我们用“\2”将代表与第二个括号相同内容。这里我们没有使用。

用工具测试通过,发现没问题,能找出。

再简化,我们删去一些对定位无关紧要的内容,这步简化要测试,保证匹配内容同上。


title="(.*?)" href="(.*?)" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" target="_blank" onclick="LogClickCount(this,363)

我们发现target="_blank"onclick="LogClickCount(this,在其他地方也有,是不能区分的内容的匹配词,我们用.*?忽略。注意,不用括号,用括号是我们提取的内容。最后我们得到一个特征字串,通过下面特征字串可以在源码众多的字符中,

提取我们要的内容。


title="(.*?)" href="(.*?)" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" .*?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<String, Object> map = new HashMap<String, Object>();
 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<Map<String, Object>> data;
final String CSDNURL = "http://www.csdn.net/";
@Override
 protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handler = getHandler();
ThreadStart();
}
/**
  * 新开辟线程处理联网操作
  */
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 数据
  */
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;
}
/**
  * 处理联网结果,显示在listview
  * @return
  */
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() {
@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 请求网址
  * @return 网页内容的字符串
  */
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);
}
}

来源:http://blog.csdn.net/laihuan99/article/details/9144227

标签:android,正则表达式,爬虫
0
投稿

猜你喜欢

  • Java基础-Java常量和常量值

    2023-08-03 03:49:03
  • android studio 3.6.1导入项目报错提示无法下载classpath里的内容

    2021-09-28 11:02:57
  • C# 函数覆盖总结学习(推荐)

    2021-12-27 00:33:05
  • MyBatis自定义映射关系和关联查询实现方法详解

    2021-12-18 21:25:28
  • 使用newInstance()来实例化fragment并传递数据操作

    2022-07-11 15:41:57
  • Java 常见的限流算法详细分析并实现

    2022-01-05 22:11:09
  • Java Maven构建工具中mvnd和Gradle谁更快

    2022-02-15 04:39:52
  • C# 使用PictureBox实现图片按钮控件的示例步骤

    2023-04-04 21:33:29
  • C#中ExecuteNonQuery()返回值注意点分析

    2023-04-05 03:40:14
  • 详解maven配置多仓库的方法示例

    2021-06-10 14:13:22
  • C#中常用的正则表达式

    2023-10-15 21:10:42
  • 关于@CacheEvict无法解决分页缓存清除的解决思路

    2023-07-06 20:22:44
  • java实现斗地主发牌系统

    2023-06-11 01:48:40
  • Mybatis-plus多租户项目实战进阶指南

    2023-10-10 18:14:43
  • Android自定义View模仿即刻点赞数字切换效果实例

    2023-08-26 12:45:39
  • 巧用Spring中的@Order进行排序

    2023-07-13 05:53:48
  • Android中实现Webview顶部带进度条的方法

    2022-04-22 15:45:43
  • 小谈Kotlin的空处理的使用

    2022-05-05 05:23:24
  • C#实现Winform小数字键盘模拟器

    2021-08-29 12:34:25
  • C#调用dll报错:无法加载dll,找不到指定模块的解决

    2023-08-23 23:36:12
  • asp之家 软件编程 m.aspxhome.com