Google Maps Api : Part 2 – Chapter 5 : Manipulating Third-Party Data


Using Downtable Textfile
Trong 3 chương tới , chúng ta sẽ làm việc với database : US Federal Communications
Commission (FCC) Antenna Structure Registration (ASR) . Database này sẽ giúp chúng ta làm được nhiều việc để build map .

Thế tại sao lại là FCC ASR , vì nhửng lý do sau đây :

– Data free để sử dụng , dễ dàng thao tác và sử dụng .
– Nó có nhiều data , cho phép chúng ta có tầm nhìn tổng quát hơn . Nó có hơn 120.000 record .
– Latitues và longtitues đều có trong các record … và còn nhiều lý do khác .

Downloading the Database
Điều đầu tiên bạn cần là lấy dữ liệu về , download tại : Đây . ~ 23 Mb . Sau khi download về giải nén RA.dat, EN.dat, and CO.dat ra và chép vào thư mục working . Bạn không cần những cái khác .

+RA.dat là file chính , nó sẽ kết hợp các file còn lại với nhau . Nó chứa thông tin như size , address …
+EN.dat là cấu trúc của khách hàng .
+CO.dat là cấu trúc của latitue và longtitute .

RA.dat :

EN.dat :

CO.dat :

Database khá phức tạp , vì thế chúng ta không cần care về data trong database , chúng ta chỉ quan tâm tới location và thuộc tính của chúng .

Parsing CSV data
Chúng ta sẽ parsing file trên bằng simple PHP . Hãy cùng xem ví dụ sau :

<?php
// Open the Registrations and Applications Data file
$handle = @fopen("RA.dat","r");
// Parse and output the first 50 USI numbers.
$i = 0;
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 1024);
$row = explode("|",$buffer);
echo "USI#: ".$row[4]."<br />\n";
if ($i == 50) break; else $i++;
}
fclose($handle);
}
?>

Code trên chỉ đơn giản là xuất thông tin ra màn hình. Không quan trọng lắm .

Import .dat file vào database
Để import vào databse , ta cần tạo database , code tạo như sau (mysql):

CREATE TABLE fcc_location (
loc_id int(10) unsigned NOT NULL auto_increment,
unique_si_loc bigint(20) NOT NULL default '0',
lat_deg int(11) default '0',
lat_min int(11) default '0',
lat_sec float default '0',
lat_dir char(1) default NULL,
latitude double default '0',
long_deg int(11) default '0',
long_min int(11) default '0',
long_sec float default '0',
long_dir char(1) default NULL,
longitude double default '0',
PRIMARY KEY (loc_id),
KEY unique_si (unique_si_loc)
) ENGINE=MyISAM ;
CREATE TABLE fcc_owner (
owner_id int(10) unsigned NOT NULL auto_increment,
unique_si_own bigint(20) NOT NULL default '0',
owner_name varchar(200) default NULL,
owner_address varchar(35) default NULL,
owner_city varchar(20) default NULL,
owner_state char(2) default NULL,
owner_zip varchar(10) default NULL,
PRIMARY KEY (owner_id),
KEY unique_si (unique_si_own)
) ENGINE=MyISAM ;
CREATE TABLE fcc_structure (
struc_id int(10) unsigned NOT NULL auto_increment,
unique_si bigint(20) NOT NULL default '0',
date_constr date default '0000-00-00',
date_removed date default '0000-00-00',
struc_address varchar(80) default NULL,
struc_city varchar(20) default NULL,
struc_state char(2) default NULL,
struc_height double default '0',
struc_elevation double NOT NULL default '0',
struc_ohag double NOT NULL default '0',
struc_ohamsl double default '0',
struc_type varchar(6) default NULL,
PRIMARY KEY (struc_id),
KEY unique_si (unique_si),
KEY struc_state (struc_state)
) ENGINE=MyISAM;

Sau khi bạn tạo table , chạy ví dụ tiếp theo , để đưa data và database :

<?php
set_time_limit(0); // this could take a while
// Connect to the database
require($_SERVER['DOCUMENT_ROOT'] . '/db_credentials.php');
$conn = mysql_connect("localhost", $db_name, $db_pass);
mysql_select_db("googlemapsbook", $conn);
// Open the Physical Location Coordinates file
$handle = @fopen("RA.dat","r");
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
$row = explode("|",$buffer);
if ($row[3] > 0) {
// Modify things before we insert them
$row[12] = date("Y-m-d",strtotime($row[12]));
$row[13] = date("Y-m-d",strtotime($row[13]));
$row[23] = addslashes($row[23]);
$row[24] = addslashes($row[24]);
$row[30] = addslashes($row[30]);
// Formulate our query
$query = "INSERT INTO fcc_structure (unique_si, date_constr,
date_removed, struc_address, struc_city, struc_state, struc_height,
struc_elevation, struc_ohag, struc_ohamsl, struc_type)
VALUES ({$row[4]}, '{$row[12]}', '{$row[13]}', '{$row[23]}',
'{$row[24]}', '{$row[25]}', '{$row[26]}', '{$row[27]}', '{$row[28]}',
'{$row[29]}', '{$row[30]}')";
// Execute our query
$result = @mysql_query($query);
if (!$result) echo("ERROR: Duplicate structure info #{$row[4]} <br>\n");
}
}
fclose($handle);
}
echo "Done Structures. <br>\n";
// Open the Ownership Data file
$handle = @fopen("EN.dat","r");
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
$row = explode("|",$buffer);
if ($row[3] > 0) {
$row[7] = addslashes($row[7]);
$row[14] = addslashes($row[14]);
$row[16] = addslashes($row[16]);
$query = "INSERT INTO fcc_owner (unique_si_own, owner_name,
owner_address, owner_city, owner_state, owner_zip) VALUES ({$row[4]},
'{$row[7]}', '{$row[14]}','{$row[16]}', '{$row[17]}', '{$row[18]}')";
$result = @mysql_query($query);
if (!$result) {
// Newer information later in the file: UPDATE instead
$query = "UPDATE fcc_owner SET owner_name='{$row[7]}',
owner_address='{$row[14]}', owner_city='{$row[16]}',
owner_state='{$row[17]}', owner_zip='{$row[18]}'
WHERE unique_si_own={$row[4]}";
$result = @mysql_query($query);
if (!$result)
echo "Failure to import ownership for struc. #{$row[4]}<br>\n";
else
echo "Updated ownership for struc. #{$row[4]} <br>\n";
}
}
}
fclose($handle);
}
echo "Done Ownership. <br>\n";
// Open the Physical Locations file
$handle = @fopen("CO.dat","r");
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
$row = explode("|",$buffer);
if ($row[3] > 0) {
if ($row[9] == "S") $sign = -1; else $sign = 1;
$dec_lat = $sign*($row[6]+$row[7]/60+$row[8]/3600);
if ($row[14] == "W") $sign = -1; else $sign = 1;
$dec_long = $sign*($row[11]+$row[12]/60+$row[13]/3600);
$query = "INSERT INTO fcc_location (unique_si_loc, lat_deg, lat_min,
lat_sec, lat_dir, latitude, long_deg, long_min, long_sec,
long_dir, longitude) VALUES ({$row[4]},'{$row[6]}', '{$row[7]}',
'{$row[8]}', '{$row[9]}', '$dec_lat','{$row[11]}', '{$row[12]}',
'{$row[13]}', '{$row[14]}', '$dec_long')";
$result = @mysql_query($query);
if (!$result) {
// Newer information later in the file: UPDATE instead
$query = "UPDATE fcc_location SET lat_deg='{$row[6]}',
lat_min='{$row[7]}', lat_deg='{$row[8]}', lat_dir='{$row[9]}',
latitude='$dec_lat', long_deg='{$row[11]}', long_min='{$row[12]}',
long_sec='{$row[13]}', long_dir='{$row[14]}', longitude='$dec_long'
WHERE unique_si_loc='{$row[4]}'";
$result = @mysql_query($query);
if (!$result)
echo "Failure to import location for struc. #{$row[4]} <br>\n";
else
echo "Updated location for struc. #{$row[4]} <br>\n";
}
}
}
fclose($handle);
}
echo "Done Locations. <br>\n";
?>

Sử dụng dữ liệu bạn mới nạp vào
Bạn có thể dùng dữ liệu qua 3 cách :
+Sử dụng php để lọc table và đưa nó vào mảng, sau đó thao tác trong nó .
+Sử dụng lệnh Select để lấy ra kết quả bạn muốn .
+Nếu version của bạn có hỗ trợ views, tạo views và dùng php để trỏ tới nó.

Cách 1 : đưa dữ liệu vào mảng và thao tác nó :

<?php
// Connect to the database
require($_SERVER['DOCUMENT_ROOT'] . '/db_credentials.php');
$conn = mysql_connect("localhost", $db_name, $db_pass);
mysql_select_db("googlemapsbook", $conn);
// Create our temporary holding arrays
$hawaiian_towers = array();
$usi_list = array();
// Get a list of the structures in Hawaii
$structures = mysql_query("SELECT * FROM fcc_structure WHERE struc_state='HI'");
for($i=0; $i<mysql_num_rows($structures); $i++) {
$row = mysql_fetch_array($structures, MYSQL_ASSOC);
$hawaiian_towers[$row['unique_si']] = $row;
$usi_list[] = $row['unique_si'];
}
unset($structures);
// Get all of the owners for the above structures
$owners = mysql_query("SELECT * FROM fcc_owner
WHERE unique_si_own IN (".implode(",",$usi_list).")");
for($i=0; $i<mysql_num_rows($owners); $i++) {
$row = mysql_fetch_array($owners, MYSQL_ASSOC);
$hawaiian_towers[$row['unique_si_own']] =
array_merge($hawaiian_towers[$row['unique_si_own']],$row);
}
unset($owners);
// Figure out the location of each of the above structures
$locations = mysql_query("SELECT * FROM fcc_location
WHERE unique_si_loc IN (".implode(",",$usi_list).")");
for($i=0; $i<mysql_num_rows($locations); $i++) {
$row = mysql_fetch_array($locations,MYSQL_ASSOC);
$hawaiian_towers[$row['unique_si_loc']] =array_merge($hawaiian_towers[$row['unique_si_loc']],$row);
}
unset($locations);
echo memory_get_usage();
?>

Cách 2 : Thao tác thông qua database với các lệnh SQL

<?php
// Connect to the database
require($_SERVER['DOCUMENT_ROOT'] . '/db_credentials.php');
$conn = mysql_connect("localhost", $db_name, $db_pass);
mysql_select_db("googlemapsbook", $conn);
$query = "SELECT * FROM fcc_structure, fcc_owner, fcc_location
WHERE struc_state='HI' AND owner_state='HI'
AND unique_si=unique_si_own AND unique_si=unique_si_loc";
$result = mysql_query($query, $conn);
$joiner = '';
$count = 0;
?>
var markers = [
<?php while($row = mysql_fetch_assoc($result)): ?>
<?= $joiner ?>
{
'latitude': <?= $row['latitude'] ?>,
'longitude': <?= $row['longitude'] ?>,
'name': '<?= addslashes($row['struc_address']) ?>'
}
<?
$joiner = ',';
$count++;
?>
<?php endwhile; ?>
];
/* Memory used at the end of the script: <? echo memory_get_usage(); ?> */
/* Output <?= $count ?> points */

Screen Scrapping
Là bắt link từ trang web khác để đưa dữ liệu vào database . Ý tưởng là : download page , sử dụng CURL or wget, sau đó sử dụng vòng lặp và regular expression hoặc chuỗi để tìm dữ liệu mình muốn , và đưa nó vào database .

Ví dụ về scrapping :
Chúng ta sẽ thử copy dữ liệu từ : http://googlemapsbook.com/
chapter5/scrape_me.html .
File đó có dạng như sau :

(After about 10 lines of header HTML you'll find this...)
<!-- Content Body -->
<table border="1" width="100%">
<tr>
<td >Country</td>
<td >Capital City</td>
<td >Latitude</td>
<td >Longitude</td></tr>
<tr><td>Afghanistan</td>
<td>Kabul</td>
<td>34.28N</td>
<td>69.11E</td></tr>
<tr><td>Albania</td>
<td>Tirane</td>
<td>41.18N</td>
<td>19.49E</td></tr>
<tr><td>Algeria</td>
<td>Algiers</td>
<td>36.42N</td>
<td>03.08E</td></tr>
(and 190 countries later...)
<tr><td>Zambia</td>
<td>Lusaka</td>
<td>15.28S</td>
<td>28.16E</td></tr>
<tr><td>Zimbabwe</td>
<td>Harare</td>
<td>17.43S</td>
<td>31.02E</td>
</tr>
</table>
<!-- Content Body End -->

Điều đầu tiên bạn cần làm là sử dụng wget để save trang về ,hoặc dùng hàm $url=fopen(“Liên kết để chúng ta lấy dữ liệu”, r) cũng được .

<?php
// Open the file and the database
$handle = @fopen("scrape_me.html","r");
$conn = mysql_connect("localhost","username","password");
mysql_select_db("geocoding_experiment",$conn);
// Status flags and temporary variables
$in_main_table = false;
$count = 0;
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
// Look for "<!-- Content Body -->"
if (trim($buffer) == "<!-- Content Body -->") {
$in_main_table = true;
continue;
}
// For each line that has "latlongtable" in it trim
if ($in_main_table && strstr($buffer,'class="latlongtable"') !== false) {
// Dig out the part we care about
$interesting_data = trim(strip_tags($buffer));
switch($count % 4) {
case 0:
// Country Info
$city = array(); // reset
$city[0] = addslashes($interesting_data);
break;
case 1:
// Capital City Info
$city[1] = addslashes($interesting_data);
break;
case 2:
// Latitude Information (determine sign)
$latitude = substr($interesting_data,0,strlen($interesting_data)-1);
if (substr($interesting_data,-1,1) == 'S') $sign = "-";
else $sign = "";
$city[2] = $sign.$latitude;
break;
case 3:
//Longitude Information (determine sign)
$longitude = substr($interesting_data,0,strlen($interesting_data)-1);
if (substr($interesting_data,-1,1) == 'W') $sign = "-";
else $sign = "";
$city[3] = $sign.$longitude;
echo implode(" ",$city)."<br />";
// Write to the database
$result = mysql_query("INSERT INTO capital_cities
(country,capital,lat,lng) VALUES ('".implode("','",$city)."')");
break;
} // switch
// Increment our counter
$count++;
// Stop when we find "<!-- Content Body End -->"
if ($buffer == "<!-- Content Body End -->") break;
} // if
} // while
} // if
fclose($handle);
?>

Sau khi chạy lệnh trên, thì database của ta như sau :

CREATE TABLE capital_cities (
uid int(11) NOT NULL auto_increment,
country text NOT NULL,
capital text NOT NULL,
lat float NOT NULL default '0',
lng float NOT NULL default '0',
PRIMARY KEY (uid),
KEY lat (lat,lng)
) ENGINE=MyISAM;
Advertisements
%d bloggers like this: