概述
有时候我们需要去查询某些地点的坐标,那么我们可以用百度提供的坐标拾取系统http://api.map.baidu.com/lbsapi/getpoint/index.html,但是会发现它只能一个一个的查,还要不停的点击,要是查询的量特别大,比如说要查某个省的所有村,甚至全国所有村的坐标怎么办,人工查寻绝对会累趴下。所以我就写了一个这样的工具:自动查取地点坐标工具
功能
现在这个工具主要是针对的村和镇,因为查询市,县范围比较大,百度的坐标拾取系统也经常拾取不到坐标。
1.数据框要求输入是json格式
2.结果框输出的也是json格式
原理
原理主要就是利用webbrowser控件与页面元素交互,例如实现自动点击,监控页面变化做出下一步相应的操作,下面我会详细讲解代码
主要代码逻辑
点击事件里声明了一条线程,并且让webbrowser跳转到百度坐标拾取系统,但是并没有开始线程,为什么现在不开始线程呢,因为如果现在开始线程可能什么页面元素也捕捉不到,现在页面还没有加载完,所以只有等页面加载完了才能去与页面交互
private void button1_Click(object sender, EventArgs e) { this.button1.Enabled = false; webBrowser1.Navigate("http://api.map.baidu.com/lbsapi/getpoint/index.html");//加载初始化页面 th = new Thread(new ThreadStart(getGps)); th.IsBackground = false; isfirst = true; islast = false; }
webBrowser1_DocumentCompleted事件是页面加载完激发的事件,线程在这里开始
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { isCompel = true; if (isfirst) { isfirst = false; th.Start(); } }
页面加载完成后,开始操作页面
//填写地址 HtmlElement htmlGpsName = doc.GetElementById("localvalue"); htmlGpsName.SetAttribute("value", d.city + d.village); //点击查询 HtmlElement htmlBut = doc.GetElementById("localsearch"); htmlBut.InvokeMember("click");
然后又添加了一个timer控件,这个控件会隔断时间轮询一个方法,那么timer控件主要在这里得作用是什么呢?当利用webbrowser点击百度拾取坐标系统的百度一下按钮时,页面会异步加载一些数据,这时webBrowser1_DocumentCompleted就无能为力了,我们利用timer执行一个方法监视页面的变化当出现特定的某些内容时说明页面已经加载完成,此时我们就可以执行下一步的页面操作了,timer的作用就是在这里监视页面变化的作用。
private void timer1_Tick(object sender, EventArgs e) { checkComplete(); } //页面抓取数据 坐标 public void checkComplete() { result r = new result(); HtmlDocument doc = this.webBrowser1.Document; if (doc.Body.InnerHtml.Contains("功能简介")) { //如果一直有 功能简介 这些字样说明点击按钮页面还没有加载 return; } this.timer1.Enabled = false; if (doc.Body.InnerHtml.Contains("id=no0")) { HtmlElement rightdiv = doc.GetElementById("txtPanel"); bool ishave = false; foreach (HtmlElement e in rightdiv.Children[0].Children) { r.village = villageName; r.twon = twonName; r.county = countyName; r.city = cityName; r.provice = proviceName; ishave = false; //判断页面中有没有查询到该村 HtmlElement ap = e.GetElementsByTagName("div")[0]; if (ap.InnerText.Contains(villageName)) { if (ap.InnerHtml.Contains(cityName) && (ap.InnerHtml.Contains(villageName) || ap.InnerHtml.Contains(villageName.Replace("社区", "区")))) { string Coordinate = reg_zb.Match(ap.InnerHtml).Value; r.Coordinate = Coordinate; results.Add(r); ishave = true; break; } } } if (!ishave) { //没有该村记录 results.Add(r); } //停止定时页面加载 } if (doc.Body.InnerHtml.Contains("没有找到相关的地点")) { results.Add(r); } //如果是最后一条记录 if (!islast) { webBrowser1.Navigate("http://api.map.baidu.com/lbsapi/getpoint/index.html"); } else { this.txt_result.Text = JsonConvert.SerializeObject(this.results); this.button1.Enabled = true; } }
源码
由于用工具写的博客不能插入下载的文件,所以在这里贴出源码,json用的是第三方的:Newtonsoft.Json
大家学习了这个以后会掌握webbrowser与页面交互的方法,举一反三,能够极大的方便工作和生活,写出更多的自动化程序,也希望大家能够分享出来方便他人
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Collections; using System.Text.RegularExpressions; using System.Threading; using Newtonsoft.Json; using System.IO; //1.点击开始按钮,加载初始化页面,同时声明多线程 getgps方法 //2.浏览器家在完成以后触发webBrowser1_DocumentCompleted 事件,将iscompel初始化true,表示加载完成页面可以进行下一步操作,同时isfirst变为false,说明th.start只执行一次 //3.开始执行线程getGps方法 //while (!isCompel) // { // Thread.Sleep(200); // } //判断页面有没有加载完成,没有完成就等待页面加载完成 //4.读取相关,村,镇等信息 //5.设置timer=true,开始抓去页面 //6.抓去完也面上的信息后设置timer=false,并且设置浏览器跳转页面 //7.线程getgps()继续等待iscompel完成,完成后继续从2开始 namespace mapCoordinate { public partial class Form1 : Form { string villageName = string.Empty; string cityName = string.Empty; string proviceName = string.Empty; string twonName = string.Empty; string countyName = string.Empty; List<result> results = new List<result>(); Regex noid = new Regex(@"no\d+ "); Regex reg_zb = new Regex(@"\d+\.\d+,\d+\.\d+ ", RegexOptions.IgnorePatternWhitespace); Thread th = null; bool islast = false; StringBuilder sbNoCun = new StringBuilder(); StringBuilder sb = new System.Text.StringBuilder(); bool isCompel = false;//是否加载完成 bool isfirst = false; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { } public void getGps() { List<data> dt = getVillageName(); if (dt.Count == 0) { this.Invoke(new Action(() => { this.timer1.Enabled = true; })); this.button1.Enabled = true; return; } int i = 0; foreach (data d in dt) { i++; //iscompel加载没有完成等待 while (!isCompel) { Thread.Sleep(200); } isCompel = false; Thread.Sleep(2000); HtmlDocument doc = null; this.Invoke(new Action(() => { doc = this.webBrowser1.Document; })); cityName = d.city; villageName = d.village; proviceName = d.provice; HtmlElement htmlGpsName = doc.GetElementById("localvalue"); htmlGpsName.SetAttribute("value", d.city + d.village); HtmlElement htmlBut = doc.GetElementById("localsearch"); htmlBut.InvokeMember("click"); this.Invoke(new Action(() => { this.timer1.Enabled = true; })); if (i == dt.Count) { islast = true; } } } //要查询的数据源 public List<data> getVillageName() { List<data> dt = JsonConvert.DeserializeObject<List<data>>(this.txt_data.Text); return dt; } private void button1_Click(object sender, EventArgs e) { this.button1.Enabled = false; webBrowser1.Navigate("http://api.map.baidu.com/lbsapi/getpoint/index.html");//加载初始化页面 th = new Thread(new ThreadStart(getGps)); th.IsBackground = false; isfirst = true; islast = false; } //定时器 private void timer1_Tick(object sender, EventArgs e) { checkComplete(); } //页面抓取数据 坐标 public void checkComplete() { result r = new result(); HtmlDocument doc = this.webBrowser1.Document; if (doc.Body.InnerHtml.Contains("功能简介")) { //如果一直有 功能简介 这些字样说明点击按钮页面还没有加载 return; } this.timer1.Enabled = false; if (doc.Body.InnerHtml.Contains("id=no0")) { HtmlElement rightdiv = doc.GetElementById("txtPanel"); bool ishave = false; foreach (HtmlElement e in rightdiv.Children[0].Children) { r.village = villageName; r.twon = twonName; r.county = countyName; r.city = cityName; r.provice = proviceName; ishave = false; //判断页面中有没有查询到该村 HtmlElement ap = e.GetElementsByTagName("div")[0]; if (ap.InnerText.Contains(villageName)) { if (ap.InnerHtml.Contains(cityName) && (ap.InnerHtml.Contains(villageName) || ap.InnerHtml.Contains(villageName.Replace("社区", "区")))) { string Coordinate = reg_zb.Match(ap.InnerHtml).Value; r.Coordinate = Coordinate; results.Add(r); ishave = true; break; } } } if (!ishave) { //没有该村记录 results.Add(r); } //停止定时页面加载 } if (doc.Body.InnerHtml.Contains("没有找到相关的地点")) { results.Add(r); } //如果是最后一条记录 if (!islast) { webBrowser1.Navigate("http://api.map.baidu.com/lbsapi/getpoint/index.html"); } else { this.txt_result.Text = JsonConvert.SerializeObject(this.results); this.button1.Enabled = true; } } private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { isCompel = true; if (isfirst) { isfirst = false; th.Start(); } } } }
声明
写博客辛苦,希望大家能点个赞,关注我,转载需注明出去。