Bản đồ các tỉnh của Việt Nam

Trong công việc, tôi được giao một task như sau: hiển thị danh sách các tỉnh / thành phố của Việt Nam; khi click vào từng tỉnh thì hiển thị trên bản đồ tỉnh đó. Tôi sẽ chia sẽ lại với các bạn các bước mà tôi đã thực hiện. Crawl dữ liệu Đầu tiên,

Trong công việc, tôi được giao một task như sau: hiển thị danh sách các tỉnh / thành phố của Việt Nam; khi click vào từng tỉnh thì hiển thị trên bản đồ tỉnh đó. Tôi sẽ chia sẽ lại với các bạn các bước mà tôi đã thực hiện.

Crawl dữ liệu

Đầu tiên, tôi sẽ lấy danh sách tên các tỉnh của Việt Nam cùng địa chỉ Wikipedia của tỉnh đó. Lý do tôi sử dụng Wikipedia vì ở trang chi tiết từng tỉnh có thông tin tọa độ (kinh độ vĩ độ).

Danh sách các tỉnh / thành phố của Việt Nam ở địa chỉ sau:

Provinces of Vietnam – Wikipedia

Tôi sẽ sử dụng PHP để bóc tách cấu trúc HTML của trang web và lấy ra danh sách tỉnh. Sau khi có danh sách, tôi sẽ thực hiện vòng lặp để gọi trang chi tiết của từng tỉnh và lấy ra kinh độ vĩ độ.

File get_province_list.php như sau:

<?php/**
* Lấy mã HTML của trang web.
* @param string $url Địa chỉ trang web
* @return string Mã HTML
*/functiongetHtml(string$url):string{$curl=curl_init($url);curl_setopt_array($curl,[CURLOPT_RETURNTRANSFER=>true,CURLOPT_SSL_VERIFYPEER=>false,CURLOPT_FOLLOWLOCATION=>true,CURLOPT_SSL_VERIFYPEER=>false,CURLOPT_SSL_VERIFYHOST=>false]);$resp=curl_exec($curl);curl_close($curl);return$resp;}/**
* Bóc tách mã HTML, lấy danh sách các tỉnh / thành phố của Việt Nam.
*/functiongetProvinceList(string$html):array{$doc=newDomDocument();
   @$doc->loadHTML($html);$table=$doc->getElementsByTagName('table')->item(2);$rows=$table->getElementsByTagName('tr');$provinceList=[];foreach($rowsas$idx=>$row){// Dòng header không có thẻ tdif($idx==0){continue;}$cols=$row->getElementsByTagName('td');$firstCell=$cols->item(0);$link=$firstCell->getElementsByTagName('a')->item(0);$provinceName=$link->nodeValue;$provinceName=str_replace([' Province',' City'],['',''],$provinceName);$url=$link->getAttribute('href');$provinceList[]=['name'=>$provinceName,'url'=>'https://en.m.wikipedia.org'.$url];}return$provinceList;}/**
* Lấy tọa độ của từng tỉnh từ trang Wikipedia của tỉnh đó.
*/functiongetCoordinatesOfProvince(string$url):array{$html=getHtml($url);$doc=newDomDocument();
   @$doc->loadHTML($html);$xpath=newDOMXpath($doc);$elems=$xpath->query("//span[@class='geo-dec']");$summary=$elems[0]->textContent;echo$summary.PHP_EOL;$lat=0;$lng=0;$regex='/([d.]+)°N ([d.]+)°E/';if(preg_match($regex,$summary,$maches)){$lat=floatval($maches[1]);$lng=floatval($maches[2]);}return[$lat,$lng];}/**
* Lưu đầu ra JSON ra file.
*/functionwriteToJsonFile(array$provinceList):void{$filePath='data/provinceList.json';$json=json_encode($provinceList,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE);file_put_contents($filePath,$json);}functionmain():void{$html=getHtml('https://en.m.wikipedia.org/wiki/Provinces_of_Vietnam');$provinceList=getProvinceList($html);foreach($provinceListas$i=>$province){[$lat,$lng]=getCoordinatesOfProvince($province['url']);echo$province['name'].PHP_EOL.$lat.', '.$lng.PHP_EOL.PHP_EOL;$provinceList[$i]['lat']=$lat;$provinceList[$i]['lng']=$lng;unset($provinceList[$i]['url']);}writeToJsonFile($provinceList);}main();

Thực hiện script:

php get_province_list.php

Sau khi thực hiện xong script, chúng ta sẽ được file đầu ra data/provinceList.json như sau:

[{"name":"Bắc Giang","lat":21.333,"lng":106.333},{"name":"Bắc Kạn","lat":22.167,"lng":105.833},{"name":"Cao Bằng","lat":22.667,"lng":106},{"name":"Hà Giang","lat":22.75,"lng":105},{"name":"Lạng Sơn","lat":21.75,"lng":106.5},{"name":"Phú Thọ","lat":21.333,"lng":105.167},{"name":"Quảng Ninh","lat":21.25,"lng":107.333},{"name":"Thái Nguyên","lat":21.667,"lng":105.833},{"name":"Tuyên Quang","lat":22.117,"lng":105.25},{"name":"Lào Cai","lat":22.333,"lng":104},{"name":"Yên Bái","lat":21.5,"lng":104.667},{"name":"Điện Biên","lat":21.383,"lng":103.017},{"name":"Hòa Bình","lat":20.333,"lng":105.25},{"name":"Lai Châu","lat":22,"lng":103},{"name":"Sơn La","lat":21.167,"lng":104},{"name":"Bắc Ninh","lat":21.083,"lng":106.167},{"name":"Hà Nam","lat":20.583,"lng":106},{"name":"Hải Dương","lat":20.917,"lng":106.333},{"name":"Hưng Yên","lat":20.833,"lng":106.083},{"name":"Nam Định","lat":20.25,"lng":106.25},{"name":"Ninh Bình","lat":20.25,"lng":105.833},{"name":"Thái Bình","lat":20.5,"lng":106.333},{"name":"Vĩnh Phúc","lat":21.3,"lng":105.6},{"name":"Hà Nội","lat":21.02833,"lng":105.85417},{"name":"Hải Phòng","lat":20.865139,"lng":106.683833},{"name":"Hà Tĩnh","lat":18.333,"lng":105.9},{"name":"Nghệ An","lat":19.333,"lng":104.833},{"name":"Quảng Bình","lat":17.5,"lng":106.333},{"name":"Quảng Trị","lat":16.75,"lng":107},{"name":"Thanh Hóa","lat":20,"lng":105.5},{"name":"Thừa Thiên-Huế","lat":16.333,"lng":107.583},{"name":"Đắk Lắk","lat":12.667,"lng":108.05},{"name":"Đắk Nông","lat":11.983,"lng":107.7},{"name":"Gia Lai","lat":13.75,"lng":108.25},{"name":"Kon Tum","lat":14.75,"lng":107.917},{"name":"Lâm Đồng","lat":11.95,"lng":108.433},{"name":"Bình Định","lat":14.167,"lng":109},{"name":"Bình Thuận","lat":10.933,"lng":108.1},{"name":"Khánh Hòa","lat":12.25,"lng":109.2},{"name":"Ninh Thuận","lat":11.75,"lng":108.833},{"name":"Phú Yên","lat":13.167,"lng":109.167},{"name":"Quảng Nam","lat":15.58333,"lng":107.91667},{"name":"Quảng Ngãi","lat":15,"lng":108.667},{"name":"Đà Nẵng","lat":16.06944,"lng":108.20972},{"name":"Bà Rịa-Vũng Tàu","lat":10.583,"lng":107.25},{"name":"Bình Dương","lat":11.167,"lng":106.667},{"name":"Bình Phước","lat":11.75,"lng":106.917},{"name":"Đồng Nai","lat":11.117,"lng":107.183},{"name":"Tây Ninh","lat":11.333,"lng":106.167},{"name":"Hồ Chí Minh","lat":10.8,"lng":106.65},{"name":"An Giang","lat":10.5,"lng":105.167},{"name":"Bạc Liêu","lat":9.25,"lng":105.75},{"name":"Bến Tre","lat":10.167,"lng":106.5},{"name":"Cà Mau","lat":9.083,"lng":105.083},{"name":"Đồng Tháp","lat":10.667,"lng":105.667},{"name":"Hậu Giang","lat":9.783,"lng":105.467},{"name":"Kiên Giang","lat":10,"lng":105.167},{"name":"Long An","lat":10.667,"lng":106.167},{"name":"Sóc Trăng","lat":9.667,"lng":105.833},{"name":"Tiền Giang","lat":10.417,"lng":106.167},{"name":"Trà Vinh","lat":9.833,"lng":106.25},{"name":"Vĩnh Long","lat":10.167,"lng":106},{"name":"Cần Thơ","lat":10.033,"lng":105.783}]

Hiển thị trên bản đồ

Tôi sử dụng Leaflet và OpenStreetMap để hiển thị bản đồ. Ngoài ra tôi cũng dùng Vue để code gọn hơn. File province_list.html như sau:

<!DOCTYPEhtml><html><head><metahttp-equiv="content-type"content="text/html; charset=UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Bản đồ tỉnh thành phố</title><linkrel="stylesheet"href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"></head><body><divid="app"class="container-fluid"><divclass="row"><divclass="col-md-2"><divclass="custom-scrollbar overflow-auto vh-100 pt-3"><ul><liv-for="province in provinceList"><ahref=""@click.prevent="chooseProvince(province)">{{province.name}}</a></li></ul></div></div><divclass="col-md-10 p-0"><divref="mapContainer"class="vh-100"></div></div></div></div><linkrel="stylesheet"href="https://unpkg.com/[email protected]/dist/leaflet.css"/><scriptsrc="https://unpkg.com/[email protected]/dist/leaflet.js"></script><scriptsrc="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script><scriptsrc="js/script.js"></script></body></html>

File js/script.js như sau:

asyncfunctiongetProvinceList(){const data =awaitfetch('data/provinceList.json').then(resp=> resp.json());return data;}functioninitVue(provinceList){newVue({
       el:'#app',data(){return{
               provinceList,
               map:null};},mounted(){this.initMap();this.addMarkers();},

       methods:{initMap(){this.map =L.map(this.$refs.mapContainer,{
                   attributionControl:false,
                   center:[21.0819,105.6363],
                   zoom:8});L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(this.map);},addMarkers(){this.provinceList.forEach(province=>{const latlng =L.latLng(province.lat, province.lng);const marker =L.marker(latlng).addTo(this.map).bindPopup(province.name);
                   province.latlng = latlng;
                   province.marker = marker;});},chooseProvince(province){this.map.panTo(province.latlng);
               province.marker.openPopup();}}});}asyncfunctionmain(){const provinceList =awaitgetProvinceList();initVue(provinceList);}main();

Kết quả:

Demo

Hy vọng bài viết này có thể giúp đỡ được bạn nào đó cũng được giao task tương tự.

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ