在我的上一篇文章中我介绍了windows phone 7的gb2312解码,
http://www.cnblogs.com/qingci/archive/2011/11/25/2263124.html
解决了下载的Html乱码问题,这一篇,我将介绍关于windows phone 7解析html数据,以便我们获得想要的数据.
这里,我先介绍一个类库HtmlAgilityPack,(上一篇文章也是通过这个工具来解码的). 类库的dll文件我会随demo一起提供
这里,我以新浪新闻为例来解析数据
先看看网页版的新浪新闻
http://news.sina.com.cn/w/sd/2011-11-27/070023531646.shtml
然后我们看一下他的源文件,
发现新闻内容的结构是
<div class="blkContainerSblk"> <h1 id="artibodyTitle" pid="1" tid="1" did="23531646" fid="1666">title</h1> <div class="artInfo"><span id="art_source"><a href="http://www.sina.com.cn">http://www.sina.com.cn</a></span> <span id="pub_date">pub_date</span> <span id="media_name"><a href="">media_name</a> <a href=""></a> </span></div> <!-- 正文内容 begin --> <!-- google_ad_section_start --> <div class="blkContainerSblkCon" id="artibody"></div> </div>
大部分还有ID属性,这更适合我们去解析了。
接下来我们开始去解析
第一: 引用HtmlAgilityPack.dll文件
第二:用WebClient或者WebRequest类来下载HTML页面然后处理成字符串。
public delegate void CallbackEvent(object sender, DownloadEventArgs e);
public event CallbackEvent DownloadCallbackEvent;
public void HttpWebRequestDownloadGet(string url)
{
Thread _thread = new Thread(delegate()
{
Uri _uri = new Uri(url, UriKind.RelativeOrAbsolute);
HttpWebRequest _httpWebRequest = (HttpWebRequest)WebRequest.Create(_uri);
_httpWebRequest.Method="Get";
_httpWebRequest.BeginGetResponse(new AsyncCallback(delegate(IAsyncResult result)
{
HttpWebRequest _httpWebRequestCallback = (HttpWebRequest)result.AsyncState;
HttpWebResponse _httpWebResponseCallback = (HttpWebResponse)_httpWebRequestCallback.EndGetResponse(result);
Stream _streamCallback = _httpWebResponseCallback.GetResponseStream();
StreamReader _streamReader = new StreamReader(_streamCallback,new HtmlAgilityPack.Gb2312Encoding());
string _stringCallback = _streamReader.ReadToEnd();
Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
{
if (DownloadCallbackEvent != null)
{
DownloadEventArgs _downloadEventArgs = new DownloadEventArgs();
_downloadEventArgs._DownloadStream = _streamCallback;
_downloadEventArgs._DownloadString = _stringCallback;
DownloadCallbackEvent(this, _downloadEventArgs);
}
}));
}), _httpWebRequest);
}) ;
_thread.Start();
}
// }
O(∩_∩)O! 我这个比较复杂, 总之我们下载了html的数据就行了。
贴一个简单的下载方式吧
WebClient webClenet=new WebClient();
webClenet.Encoding = new HtmlAgilityPack.Gb2312Encoding(); //加入这句设定编码
webClenet.DownloadStringAsync(new Uri("http://news.sina.com.cn/s/2011-11-25/120923524756.shtml", UriKind.RelativeOrAbsolute));
webClenet.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClenet_DownloadStringCompleted);
现在处理回调函数的 e.Result
string _result = e._DownloadString;
HtmlDocument _doc = new HtmlDocument(); //实例化HtmlAgilityPack.HtmlDocument对象
_doc.LoadHtml(_result); //载入HTML
HtmlNode _htmlNode01 = _doc.GetElementbyId("artibodyTitle"); //新闻标题的Div
string _title = _htmlNode01.InnerText;
HtmlNode _htmlNode02 = _doc.GetElementbyId("artibody"); //获取内容的div
string _content = _htmlNode02.InnerText;
// int _count= _htmlNode02.ChildNodes.Where(new Func<HtmlNode,bool>("div"));
int _divIndex = _content.IndexOf(" .blkComment");
_content= _content.Substring(0,_divIndex);
#region 新浪标签
HtmlNode _htmlNodo03 = _doc.GetElementbyId("art_source");
string _www = _htmlNodo03.FirstChild.InnerText;
string _wwwInt = _htmlNodo03.FirstChild.Attributes[0].Value;
#endregion
// string _source = _htmlNodo03;
//_htmlNodo03.ChildNodes
#region 发布时间
HtmlNode _htmlNodo04 = _doc.GetElementbyId("pub_date");
string _pub_date = _htmlNodo04.InnerText;
#endregion
#region 来源网站信息
HtmlNode _htmlNodo05 = _doc.GetElementbyId("media_name");
string _media_name = _htmlNodo05.FirstChild.InnerText;
string _modia_source = _htmlNodo05.FirstChild.Attributes[0].Value;
#endregion
Media_nameHyperlinkButton.Content = _pub_date + " " + _media_name;
Media_nameHyperlinkButton.NavigateUri = new Uri(_modia_source, UriKind.RelativeOrAbsolute);
TitleTextBlock.Text = _title;
ContentTextBlock.Text = _content;
结果如下图所示:

网页的大部分标签是没有ID属性的,不过幸运的是HtmlAgilityPack支持XPath
那就需要通过XPATH语言来查找匹配所需节点
XPath教程:http://www.w3school.com.cn/xpath/index.asp
案例下载:
http://115.com/file/dn87dl2d#
MyFramework_Test.zip
关于silverlight和wp7(windows phone 7)是默认不支持gb2312解码的,
所以从网上下载的Html大部分都是乱码。
例如:http://news.sina.com.cn/s/2011-11-25/120923524756.shtml
下面是演示一个wp7程序
1 WebClient webClenet=new WebClient();
2 webClenet.DownloadStringAsync(new Uri("http://news.sina.com.cn/s/2011-11-25/120923524756.shtml", UriKind.RelativeOrAbsolute));
3 webClenet.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClenet_DownloadStringCompleted);
4
5
6
7
8
9
10 回调事件:
11 void webClenet_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
12 {
13 string s= e.Result;
14 }
调试发现

几乎全部是乱码问题.
将编码设为utf-8同样是乱码。
于是引用了一个开源的库HtmlAgilityPack(包含编码还处理HTML节点)
下载地址为:http://www.codeplex.com/htmlagilitypack
将HtmlAgilityPack.dll引用到项目中,这时会弹出一个提示,大概就是这不是一个windows phone的类库,不理会,直接确定。
然后修改一下我们的代码
WebClient webClenet=new WebClient();
webClenet.Encoding = new HtmlAgilityPack.Gb2312Encoding(); //加入这句设定编码
webClenet.DownloadStringAsync(new Uri("http://news.sina.com.cn/s/2011-11-25/120923524756.shtml", UriKind.RelativeOrAbsolute));
webClenet.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClenet_DownloadStringCompleted);
调试一下,结果如图:

终于看到我们的中文啦。
同时,HtmlAgilityPack不仅帮我们解决了gb2312的编码问题,它还是我们解析HTML的利器哦~!
不好意思,之前忘记补上案例了,今天补上
下载地址
前几天看到淘宝的Android客户端,有种促销的功能,当点击促销的时候连接的淘宝促销wap页面,然后点击商品后又跳到程序的商品详情页面,显示商品的详情。
这是一种客户端和web的交互行为。
在wp7中有个事件
private void webBrowser_Navigating(object sender, NavigatingEventArgs e){}
这个事件就是当你在触发wap页面的某个导航按钮时(超链接或者其他导航按钮)。会触发该事件。然后获得导航的URL,和参数信息。
通过这个事件,可以完美实现客户端和web的交互行为。
public void getXML(String url) throws XmlPullParserException,IOException,URISyntaxException
{
String xmlString=downloadXML(url);
XmlPullParserFactory factory=XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser parser=factory.newPullParser();
parser.setInput(new StringReader(xmlString));
int eventType=parser.getEventType();
List<Forecast_conditions> conditionsList=new ArrayList<Forecast_conditions>();
Forecast_conditions forecast_conditions=null;
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_DOCUMENT) {
System.out.println("Start Document");
}else if (eventType== XmlPullParser.START_TAG) {
System.out.println("Start Tag "+parser.getName());
if (parser.getName().equals("forecast_conditions"))
{
forecast_conditions=new Forecast_conditions();
}
if (parser.getName().equals("day_of_week")) {
forecast_conditions.setDay_of_week(parser.getAttributeValue(0));
}else if (parser.getName().equals("low")) {
forecast_conditions.setLow(parser.getAttributeValue(0));
}else if (parser.getName().equals("high")) {
forecast_conditions.setHigh(parser.getAttributeValue(0));
}else if (parser.getName().equals("icon")) {
try {
forecast_conditions.setIcon(parser.getAttributeValue(0));
} catch (Exception e) {
// TODO: handle exception
}
}else if (parser.getName().equals("condition")) {
try {
forecast_conditions.setCondition(parser.getAttributeValue(0));
} catch(Exception e){
}
}
/* int size=parser.getAttributeCount();
for (int i = 0; i < size; i++) {
System.out.println("AttributeName "+parser.getAttributeName(i));
System.out.println("AttributeValue"+parser.getAttributeValue(i));
} */
}else if(eventType== XmlPullParser.END_TAG){
System.out.println("End Tag "+parser.getName());
if (parser.getName().equals("forecast_conditions")) {
conditionsList.add(forecast_conditions);
}
}else if(eventType==XmlPullParser.TEXT){
System.out.println("Text "+parser.getText());
}
eventType=parser.next();
}
System.out.println("End Document");
bindToListView(conditionsList);
//XmlUtils.
}
本实例是不完整实例。 初学Android, 很多地方不规范。 仅供参考。
public void bindToListView(List<Forecast_conditions> conditionsList)
{
//SimpleAdapter simpleAdapter=new SimpleAdapter(this,conditionsList,R.layout.list_item, new String[]{"day_of_week","low","high","icon","condition"},new int[]{R.id.WeekTextView,R.id.lowTextView,R.id.HighTextView,R.id.imageView1,R.id.CondtionTextView});
// SimpleAdapter simpleAdapter=new
// m_weatherListView.setAdapter(simpleAdapter);\
List<HashMap<String, Object>> hashMaplst=new ArrayList<HashMap<String,Object>>();
for (Forecast_conditions forecast_conditions : conditionsList) {
HashMap<String, Object> item=new HashMap<String, Object>();
item.put("day_of_week", forecast_conditions.getDay_of_week());
item.put("low", forecast_conditions.getLow());
item.put("high", forecast_conditions.getHigh());
item.put("icon", forecast_conditions.getHigh());
item.put("condition", forecast_conditions.getCondition());
hashMaplst.add(item);
}
SimpleAdapter simpleAdapter=new SimpleAdapter(this,hashMaplst,R.layout.list_item, new String[]{"day_of_week","low","high","icon","condition"},new int[]{R.id.WeekTextView,R.id.lowTextView,R.id.HighTextView,R.id.imageView1,R.id.CondtionTextView});
m_weatherListView.setAdapter(simpleAdapter);
}
//Forecast_conditions 是实体类
//本实例是第一次做Android从各方查来写的代码,很多地方设计不合理。 所以仅供参考 -。-
m_weatherListView是ListView控件
public String downloadXML(final String urlStr)
{
StringBuffer sb=new StringBuffer();
String line=null;
BufferedReader buffer=null;
try {
URL url=new URL(urlStr);
HttpURLConnection urlConn=(HttpURLConnection)url.openConnection();
InputStream inputStream = urlConn.getInputStream();
buffer=new BufferedReader(new InputStreamReader(inputStream));
while ((line= buffer.readLine()) != null) {
sb.append(line);
}
} catch (Exception e) {
e.printStackTrace();
} finally{
try {
buffer.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
return sb.toString();
}
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(UrlManager.Login());
myRequest.Method = "POST";
myRequest.ContentType = "application/x-www-form-urlencoded";
myRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), myRequest);
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
System.IO.Stream postStream = request.EndGetRequestStream(asynchronousResult);
// Prepare Parameters String
string parametersString = "username=用户名&password=密码";
//foreach (KeyValuePair<string, string> parameter in parameters)
//{
// parametersString = parametersString + (parametersString != "" ? "&" : "") + string.Format("{0}={1}", parameter.Key, parameter.Value);
//}
byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(parametersString);
// Write to the request stream.
postStream.Write(byteArray, 0, parametersString.Length);
postStream.Close();
// Start the asynchronous operation to get the response
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
// Close the stream object
streamResponse.Close();
streamRead.Close();
}
前几天做项目用到, 代码贴给大家。
/// <summary>
/// 获取当前位置的经纬度
/// </summary>
/// <returns></returns>
public static double[] GetLocationProperty()
{
double[] latLong = new double[2];
GeoCoordinateWatcher watcher = new GeoCoordinateWatcher();
watcher.TryStart(false,TimeSpan.FromMilliseconds(1000));
GeoCoordinate coord = watcher.Position.Location;
if (coord.IsUnknown != true)
{
latLong[0] = coord.Latitude;
latLong[1] = coord.Longitude;
}
return latLong;
}
#region 两个经纬度之差求的距离
private const double EARTH_RADIUS = 6378.137;
private static double rad(double d)
{
return d * Math.PI / 180.0;
}
public static double GetDistance(double lat1, double lng1, double lat2, double lng2)
{
double radLat1 = rad(lat1);
double radLat2 = rad(lat2);
double a = radLat1 - radLat2;
double b = rad(lng1) - rad(lng2);
double s = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) +
Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2)));
s = s * EARTH_RADIUS;
s = Math.Round(s * 10000) / 10000;
return s;
}
#endregion
//URL接口来自诺基亚地图
public static Uri Get_CityNameOnMap(double slatitude, double slongitude)
{
string urlString = "http://loc.desktop.maps.svc.ovi.com/geocoder/rgc/1.0?" + "lat=" + slatitude + "&long=" + slongitude + "&output=json";
return new Uri(urlString, UriKind.RelativeOrAbsolute);
}
//模拟XNA的框架(凡是在wp7中应用xna的都必须先模拟此类)
public class XNAAsyncDispatcher : IApplicationService
{
private DispatcherTimer frameworkDispatcherTimer;
public XNAAsyncDispatcher(TimeSpan dispatchInterval)
{
this.frameworkDispatcherTimer = new DispatcherTimer();
this.frameworkDispatcherTimer.Tick += new EventHandler(frameworkDispatcherTimer_Tick);
this.frameworkDispatcherTimer.Interval = dispatchInterval;
}
void IApplicationService.StartService(ApplicationServiceContext context)
{
this.frameworkDispatcherTimer.Start();
}
void IApplicationService.StopService()
{
this.frameworkDispatcherTimer.Stop();
}
void frameworkDispatcherTimer_Tick(object sender, EventArgs e)
{
FrameworkDispatcher.Update();
}
}
在App 构造函数里写 this.ApplicationLifetimeObjects.Add(new XNAAsyncDispatcher(TimeSpan.FromMilliseconds(50))); 当程序激动时就开始模拟XNA GameTimer
//后代代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.IO;
using Microsoft.Xna.Framework.Audio;
namespace Wp7_录音
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
mic.BufferReady += Default_BufferReady;
SoundEffect.MasterVolume = 1.0f;
}
MemoryStream ms;
Microphone mic = Microphone.Default;
// Wire up an event handler so we can empty the buffer when full
// Crank up the volume to max
// When the buffer's ready we need to empty it
// We'll copy to a MemoryStream
// We could push into IsolatedStorage etc
void Default_BufferReady(object sender, EventArgs e)
{
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = mic.GetData(buffer, 0, buffer.Length)) > 0)
ms.Write(buffer, 0, bytesRead);
}
// The user wants to start recording. If we've already made
// a recording, close that MemoryStream and create a new one.
// Start recording on the default device.
private void start_Click(object sender, RoutedEventArgs e)
{
if (ms != null)
ms.Close();
ms = new MemoryStream();
mic.Start();
}
// The user wants to stop recording. Checks the microphone
// is stopped. Reset the MemoryStream position.
// Play back the recording. Pitch is based on slider value
private void stop_Click(object sender, RoutedEventArgs e)
{
if (mic.State != MicrophoneState.Stopped)
mic.Stop();
ms.Position = 0;
SoundEffect se = new SoundEffect(ms.ToArray(), mic.SampleRate, AudioChannels.Mono);
//se.Play(1.0f, (float)slider1.Value, 0.0f);
se.Play();
}
}
}
本实例UI就两个Button 一个start 一个stop, 还有一个滑动条 Silder.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
int result = 0;
for (int i = 0; i < 100000; i++)
{
result += i;
}
System.Threading.Thread.Sleep(3000);
e.Result = result;
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
label1.Text =e.Result.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "正在登陆中.....";
button1.Enabled = false;
backgroundWorker1.RunWorkerAsync();
}