概述
有時候我們需要去查詢某些地點的坐標,那么我們可以用百度提供的坐標拾取系統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(); } } } }
聲明
寫博客辛苦,希望大家能點個贊,關注我,轉載需注明出去。