Google Geo APIs Team 
August 2009

This tutorial is intended for developers who are familiar with PHP/MySQL, and want to learn how to use Google Maps with a MySQL database to create a store locator-type app. After completing this tutorial, you will have a database of locations and a webpage that lets a user enter their address and see markers on a map for the locations nearest to them, within a chosen distance restriction. Since the Google Maps JavaScript API is designed to work well on modern mobile browsers, this article will show how to create a website that displays nicely on them.

The tutorial is broken up into the following steps:

Creating the Table

When you create the MySQL table, you want to pay particular attention to the lat and lng attributes. With the current zoom capabilities of Google Maps, you should only need 6 digits of precision after the decimal. To keep the storage space required for your table at a minimum, you can specify that the lat and lng attributes are floats of size (10,6). That will let the fields store 6 digits after the decimal, plus up to 4 digits before the decimal, e.g. -123.456789 degrees. Your table should also have an id attribute to serve as the primary key.

Note: This tutorial uses location data that already have latitude and longitude information needed to plot corresponding markers.

If you prefer interacting with your database through the phpMyAdmin interface, here's a screenshot of the table creation.

If you don't have access to phpMyAdmin or prefer using SQL commands instead, here's the SQL statement that creates the table. phpsqlajax_createtable.sql:

 
CREATE TABLE `markers` (
  `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
  `name` VARCHAR( 60 ) NOT NULL ,
  `address` VARCHAR( 80 ) NOT NULL ,
  `lat` FLOAT( 10, 6 ) NOT NULL ,
  `lng` FLOAT( 10, 6 ) NOT NULL
) ENGINE = MYISAM ;

Populating the Table

After creating the table, it's time to populate it with data. The sample data provided below is for about 180 pizzarias scattered across the United States. In phpMyAdmin, you can use the IMPORT tab to import various file formats, including CSV (comma-separated values). Microsoft Excel and Google Spreadsheets both export to CSV format, so you can easily transfer data from spreadsheets to MySQL tables through exporting/importing CSV files.

Here's a snippet of the sample data in CSV format. phpsqlsearch_data.csv:

 
Frankie Johnnie & Luigo Too,"939 W El Camino Real, Mountain View, CA",37.386339,-122.085823
Amici's East Coast Pizzeria,"790 Castro St, Mountain View, CA",37.38714,-122.083235
Kapp's Pizza Bar & Grill,"191 Castro St, Mountain View, CA",37.393885,-122.078916
Round Table Pizza: Mountain View,"570 N Shoreline Blvd, Mountain View, CA",37.402653,-122.079354
Tony & Alba's Pizza & Pasta,"619 Escuela Ave, Mountain View, CA",37.394011,-122.095528
Oregano's Wood-Fired Pizza,"4546 El Camino Real, Los Altos, CA",37.401724,-122.114646
...

Here's a screenshot of the import options used to transform this CSV into table data:

If you'd rather not use the phpMyAdmin interface, here's a snippet of the SQL statements that accomplish the same results. phpsqlsearch_data.sql:

 
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Frankie Johnnie & Luigo Too','939 W El Camino Real, Mountain View, CA','37.386339','-122.085823');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Amici\'s East Coast Pizzeria','790 Castro St, Mountain View, CA','37.38714','-122.083235');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Kapp\'s Pizza Bar & Grill','191 Castro St, Mountain View, CA','37.393885','-122.078916');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Round Table Pizza: Mountain View','570 N Shoreline Blvd, Mountain View, CA','37.402653','-122.079354');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Tony & Alba\'s Pizza & Pasta','619 Escuela Ave, Mountain View, CA','37.394011','-122.095528');
INSERT INTO `markers` (`name`, `address`, `lat`, `lng`) VALUES ('Oregano\'s Wood-Fired Pizza','4546 El Camino Real, Los Altos, CA','37.401724','-122.114646');
...

Finding Locations with MySQL

To find locations in your markers table that are within a certain radius distance of a given latitude/longitude, you can use a SELECT statement based on the Haversine formula. The Haversine formula is used generally for computing great-circle distances between two pairs of coordinates on a sphere. An in-depth mathemetical explanation is given byWikipedia and a good discussion of the formula as it relates to programming is on Movable Type's site.

Here's the SQL statement that will find the closest 20 locations that are within a radius of 25 miles to the 37, -122 coordinate. It calculates the distance based on the latitude/longitude of that row and the target latitude/longitude, and then asks for only rows where the distance value is less than 25, orders the whole query by distance, and limits it to 20 results. To search by kilometers instead of miles, replace 3959 with 6371.

 
SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance FROM markers HAVING distance < 25 ORDER BY distance LIMIT 0 , 20;

Outputting XML with PHP

Now that you have the table and the SQL statement, you can put them together to output the search results into an XML format that your map can retrieve through asynchronous JavaScript calls. If the code provided here does not work with your PHP configuration, read through the Outputting XML with PHP section of our Using PHP/MySQL with Google Maps article. The only difference between the various PHP code samples shown there and the code needed for this article will be the SQL statement and the rows that are outputted in the XML.

First, you should put your database connection information in a separate file. This is generally a good idea whenever you're using PHP to access a database, as it keeps your confidential information in a file that you won't be tempted to share. In public forums, we've occasionally seen people accidentally publish their database connection information when they were just trying to debug their XML-outputting code. The file should look like this, but with your own database information filled in. phpsqlsearch_dbinfo.php:

 
<?
$username="username";
$password="password";
$database="username-databaseName";
?>

Using PHP's DOM Functions to Output XML

First, check your configuration and see if you're using PHP5. If so, continue to the explanation and code below. If you aren't, then you can use echo to output XML, as used in this sample code.

In PHP, first initialize a new XML document and create the "markers" parent node. Then connect to the database, execute the SELECT by distance query discussed above on the markers table, and iterate through the results.For each row in the table (each location), create a new XML node with the row attributes as XML attributes, and append it to the parent node. Then dump the XML to the screen.

Note: Since this PHP sends user input in a MySQL statement, this code uses the mysql_real_escape_stringtechnique of avoiding SQL injection. A more elegant solution may be to use MySQL prepared statements, though implementation varies on the PHP version and DB wrapper used.

Note: If your database contains international characters or you otherwise need to force UTF-8 output, you can useutf8_encode on the outputted data.

The PHP file that does all that is shown below (phpsqlsearch_genxml.php):

 
<?php
require("phpsqlsearch_dbinfo.php"); // Get parameters from URL
$center_lat = $_GET["lat"];
$center_lng = $_GET["lng"];
$radius = $_GET["radius"]; // Start XML file, create parent node
$dom = new DOMDocument("1.0");
$node = $dom->createElement("markers");
$parnode = $dom->appendChild($node); // Opens a connection to a mySQL server
$connection=mysql_connect (localhost, $username, $password);
if (!$connection) {
  die("Not connected : " . mysql_error());
} // Set the active mySQL database
$db_selected = mysql_select_db($database, $connection);
if (!$db_selected) {
  die ("Can\'t use db : " . mysql_error());
} // Search the rows in the markers table
$query = sprintf("SELECT address, name, lat, lng, ( 3959 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) ) AS distance FROM markers HAVING distance < '%s' ORDER BY distance LIMIT 0 , 20",
  mysql_real_escape_string($center_lat),
  mysql_real_escape_string($center_lng),
  mysql_real_escape_string($center_lat),
  mysql_real_escape_string($radius));
$result = mysql_query($query); $result = mysql_query($query);
if (!$result) {
  die("Invalid query: " . mysql_error());
} header("Content-type: text/xml"); // Iterate through the rows, adding XML nodes for each
while ($row = @mysql_fetch_assoc($result)){
  $node = $dom->createElement("marker");
  $newnode = $parnode->appendChild($node);
  $newnode->setAttribute("name", $row['name']);
  $newnode->setAttribute("address", $row['address']);
  $newnode->setAttribute("lat", $row['lat']);
  $newnode->setAttribute("lng", $row['lng']);
  $newnode->setAttribute("distance", $row['distance']);
} echo $dom->saveXML();
?>

Checking That the XML Output Works

Call this PHP script from the browser to make sure it's producing valid XML. If you suspect there's a problem with connecting to your database, you may find it easier to debug if you remove the line in the file that sets the header to thetext/xml content type, as that usually causes your browser to try to parse XML and may make it difficult to see your debugging messages.

If the script is working correctly and you append reasonable sample query parameters to the URL (e.g. ?lat=37&lng=-122&radius=25), you should see XML output like this (phpsqlsearch_expectedoutput.xml):

 
<?xml version="1.0"?>
<markers><marker name="Round Table Pizza: Mountain View" address="570 N Shoreline Blvd, Mountain View, CA" lat="37.402653" lng="-122.079353" distance="0.38091455044131"/>
<marker name="Kapp's Pizza Bar & Grill" address="191 Castro St, Mountain
     View, CA" lat="37.393887" lng="-122.078918" distance="0.5596115438175"/>
<marker name="Amici's East Coast Pizzeria" address="790 Castro St, Mountain View, CA" lat="37.387138" lng="-122.083237" distance="1.0796074495809"/>
<marker name="Frankie Johnnie & Luigo Too" address="939 W El Camino Real, Mountain View, CA" lat="37.386337" lng="-122.085823" distance="1.2044231336188"/>
<marker name="Tony & Alba's Pizza & Pasta" address="619 Escuela Ave, Mountain View, CA" lat="37.394012" lng="-122.095528" distance="1.3156538737837"/><marker name="Round Table Pizza: Sunnyvale-Mary-Central Expy" address="415 N Mary Ave, Sunnyvale, CA" lat="37.390038" lng="-122.042030" distance="1.84565061776"/>
<marker name="Oregano's Wood-Fired Pizza" address="4546 El Camino Real, Los Altos, CA" lat="37.401726" lng="-122.114647" distance="2.2887425990519"/>
...
</markers>

Creating the Map

Once you are getting correct XML output in your browser, , it's time to create the map with JavaScript. If you have never created a v3 Google Map, please try some of the basic examples in the documentation to make sure you understand the basics of creating a map.

Setting Up the Page Layout

Since one of the objectives is to have this store locator display nicely in a mobile browser, you need to customize the HTML to suit mobile browsers better. First, instead of using a sidebar to display a list of all the search results, you can use a dropdown menu. A dropdown menu takes little space, and mobile browsers will display the options in a large, easy to read list once the dropdown is selected. Then, set the CSS width of your dropdown menu and map to be 100%. This will ensure that it always fills the mobile screen space.

 
 <div><select id="locationSelect" style="width:100%;visibility:hidden"></select></div>
 <div id="map" style="width: 100%; height: 80%"></div>

Searching Near a Geocode

The PHP script takes latitude and longitude parameters in order to perform the search. Since most people who use your map will know their address but not their coordinates, you can use the Geocoder class to turn their address into a coordinate. Create a button on the page and hook it up to the searchLocations function shown below which just passes in the address from the textbox to the asynchronous Geocoder.doGeocode function, gets a LatLng in response, and sends it off to the searchLocationsNear function if the geocode was successful.

 
function searchLocations() {
  var address = document.getElementById("addressInput").value;
  var geocoder = new google.maps.Geocoder();
  geocoder.geocode({address: address}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      searchLocationsNear(results[0].geometry.location);
    } else {
      alert(address + ' not found');
    }
  });
}

Loading the XML Results

After you know the latitude and longitude of the user entered location, you need to pass that to the PHP script and process the XML that is outputted. To load the XML file into the page, you can take advantage of the browser-providedXMLHttpRequest object. This object lets you retrieve a file that resides on the same domain as the requesting webpage, and is the basis of "AJAX" programming.

So, you can define your own function for loading the file, and call it downloadUrl(). The function takes two parameters:

  1. url specifies the path to the PHP script. It's usually easiest to have this reside in the same directory as the HTML so that you can just refer to it by filename.
  2. callback indicates the function that's called when the XML is returned to the JavaScript.

The function declaration is shown below:

 
function downloadUrl(url,callback) {
 var request = window.ActiveXObject ?
     new ActiveXObject('Microsoft.XMLHTTP') :
     new XMLHttpRequest;  request.onreadystatechange = function() {
   if (request.readyState == 4) {
     request.onreadystatechange = doNothing;
     callback(request.responseText, request.status);
   }
 };  request.open('GET', url, true);
 request.send(null);
}

Note: Since XMLHttpRequest is asynchronous, the callback function won't be called as soon as you invokedownloadUrl. The bigger your XML file, the longer it may take. Don't put any code after downloadUrl that relies on the markers existing already—put it inside the callback function instead.

Now that the function is defined, you can call it from your code, passing in the name of the PHP file and a callback function. In the callback function, you need to find all the "marker" elements in the XML, and iterate through them. For each marker element you find, retrieve the name, address, distance, and lat/lng attributes and pass them tocreateMarker() to create the marker, and to createOption() to create an option in the results dropdown. You can also figure out the optimal viewport for the returned results by using LatLngBounds.extend and Map.fitBounds.

 
function searchLocationsNear(center) {
  clearLocations();   var radius = document.getElementById('radiusSelect').value;
  var searchUrl = 'phpsqlajax_search.php?lat=' + center.lat() + '&lng=' + center.lng() + '&radius=' + radius;
  downloadUrl(searchUrl, function(data) {
  var xml = parseXml(data);
  var markerNodes = xml.documentElement.getElementsByTagName("marker");
  var bounds = new google.maps.LatLngBounds();
  for (var i = 0; i < markerNodes.length; i++) {
    var name = markerNodes[i].getAttribute("name");
    var address = markerNodes[i].getAttribute("address");
    var distance = parseFloat(markerNodes[i].getAttribute("distance"));
    var latlng = new google.maps.LatLng(
        parseFloat(markerNodes[i].getAttribute("lat")),
        parseFloat(markerNodes[i].getAttribute("lng")));     createOption(name, distance, i);
    createMarker(latlng, name, address);
    bounds.extend(latlng);
  }
  map.fitBounds(bounds);
 });
}

Creating Markers & the Sidebar

In the createMarker() function shown below, you just create a marker at the given LatLng, and add an event listener to the marker so that when clicked, an info window is displayed showing the name and address. Note that since API v3 permits multiple infowindows to be displayed on the map at once, you can re-use the same infowindow variable throughout the code to ensure that only one infowindow ever displays.

 
function createMarker(latlng, name, address) {
  var html = "<b>" + name + "</b> <br/>" + address;
  var marker = new google.maps.Marker({
    map: map,
    position: latlng
  });
  google.maps.event.addListener(marker, 'click', function() {
    infoWindow.setContent(html);
    infoWindow.open(map, marker);
  });
  markers.push(marker);
}

In the createOption() function shown below, you create an option element that displays the name and distance in parantheses. The value of the option is the index of the marker in the global markers array. You can use this value to open the infowindow over the marker when the option is selected.

 
function createOption(name, distance, num) {
  var option = document.createElement("option");
  option.value = num;
  option.innerHTML = name + "(" + distance.toFixed(1) + ")";
  locationSelect.appendChild(option);
}

Clearing Previous Results

Between searches, you need to remove the previously displayed infowindow, markers and dropdown options. TheclearLocations() function removes the markers by setting their map property to null, and then clears the options.

 
function clearLocations() {
  infoWindow.close();
  for (var i = 0; i < markers.length; i++) {
    markers[i].setMap(null);
  }
  markers.length = 0;   locationSelect.innerHTML = "";
  var option = document.createElement("option");
  option.value = "none";
  option.innerHTML = "See all results:";
  locationSelect.appendChild(option);
  locationSelect.style.visibility = "visible";
}

Putting It All Together

Here's a screenshot and code for the webpage that ties everything together (phpsqlsearch_map.html). When the page loads, the load function is called. This function sets up the map and the results dropdown.

 
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    <title>Google Maps AJAX + mySQL/PHP Example</title>
    <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"
            type="text/javascript"></script>
    <script type="text/javascript">
    //<![CDATA[
    var map;
    var markers = [];
    var infoWindow;
    var locationSelect;     function load() {
      map = new google.maps.Map(document.getElementById("map"), {
        center: new google.maps.LatLng(40, -100),
        zoom: 4,
        mapTypeId: 'roadmap',
        mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU}
      });
      infoWindow = new google.maps.InfoWindow();       locationSelect = document.getElementById("locationSelect");
      locationSelect.onchange = function() {
        var markerNum = locationSelect.options[locationSelect.selectedIndex].value;
        if (markerNum != "none"){
          google.maps.event.trigger(markers[markerNum], 'click');
        }
      };
   }    function searchLocations() {
     var address = document.getElementById("addressInput").value;
     var geocoder = new google.maps.Geocoder();
     geocoder.geocode({address: address}, function(results, status) {
       if (status == google.maps.GeocoderStatus.OK) {
        searchLocationsNear(results[0].geometry.location);
       } else {
         alert(address + ' not found');
       }
     });
   }    function clearLocations() {
     infoWindow.close();
     for (var i = 0; i < markers.length; i++) {
       markers[i].setMap(null);
     }
     markers.length = 0;      locationSelect.innerHTML = "";
     var option = document.createElement("option");
     option.value = "none";
     option.innerHTML = "See all results:";
     locationSelect.appendChild(option);
   }    function searchLocationsNear(center) {
     clearLocations();      var radius = document.getElementById('radiusSelect').value;
     var searchUrl = 'phpsqlsearch_genxml.php?lat=' + center.lat() + '&lng=' + center.lng() + '&radius=' + radius;
     downloadUrl(searchUrl, function(data) {
       var xml = parseXml(data);
       var markerNodes = xml.documentElement.getElementsByTagName("marker");
       var bounds = new google.maps.LatLngBounds();
       for (var i = 0; i < markerNodes.length; i++) {
         var name = markerNodes[i].getAttribute("name");         
var address = markerNodes[i].getAttribute("address");         
var distance = parseFloat(markerNodes[i].getAttribute("distance"));         
var latlng =new google.maps.LatLng(              parseFloat
(markerNodes[i].getAttribute("lat")),              parseFloat
(markerNodes[i].getAttribute("lng")));         createOption (name, distance, i);         createMarker
(latlng, name, address);         bounds
.extend(latlng);       
}       map
.fitBounds(bounds);       locationSelect
.style.visibility ="visible";       locationSelect
.onchange =function(){         
var markerNum = locationSelect.options[locationSelect.selectedIndex].value;         google
.maps.event.trigger(markers[markerNum],'click');       
};     
});   
}    function createMarker(latlng, name, address){     
var html ="<b>"+ name +"</b> <br/>"+ address;     
var marker =new google.maps.Marker({        map
: map,        position
: latlng     
});      google
.maps.event.addListener(marker,'click',function(){        infoWindow
.setContent(html);        infoWindow
.open(map, marker);     
});      markers
.push(marker);   
}    function createOption(name, distance, num){     
var option = document.createElement("option");      option
.value = num;      option
.innerHTML = name +"("+ distance.toFixed(1)+")";      locationSelect
.appendChild(option);   
}    function downloadUrl(url, callback){     
var request = window.ActiveXObject?         
newActiveXObject('Microsoft.XMLHTTP'):         
newXMLHttpRequest;      request .onreadystatechange =function(){       
if(request.readyState ==4){          request
.onreadystatechange = doNothing;          callback
(request.responseText, request.status);       
}     
};      request .open('GET', url,true);      request
.send(null);   
}    function parseXml(str){     
if(window.ActiveXObject){       
var doc =newActiveXObject('Microsoft.XMLDOM');        doc
.loadXML(str);       
return doc;     
}elseif(window.DOMParser){       
return(newDOMParser).parseFromString(str,'text/xml');     
}   
}    function doNothing(){}    //]]> 
</script> 
</head>  <bodystyle="margin:0px;padding:0px;"onload="load()">   
<div>     
<inputtype="text"id="addressInput"size="10"/>   
<selectid="radiusSelect">     
<optionvalue="25"selected>25mi</option>     
<optionvalue="100">100mi</option>     
<optionvalue="200">200mi</option>   
</select>    <inputtype="button"onclick="searchLocations()"value="Search"/>   
</div>   
<div><selectid="locationSelect"style="width:100%;visibility:hidden"></select></div>   
<divid="map"style="width:100%;height:80%"></div> 
</body>
</html>

Where to Go From Here

Now that you have a store locator for your website, consider extending it with more features. Some ideas:

  • User Location: The Android phone provides a Gears Geolocation module for determining the approximate location of a user, and the iPhone supports the W3C geolocation property. You can use this information to do a default search for the user when they first arrive at your page, and minimize the amount of typing they need to do. See this example.
  • Advanced search: Let users restrict searches by category or some attribute. Check out the Ace Hardware store locator for a great example of this.
  • Fancy infowindows: You can make your info windows more helpful by adding quick links for the user to zoom in to that location or get driving directions to/from that location.

Creating a Store Locator with PHP, MySQL & Google Maps(保存地图坐标 经纬度方法 google mysql)的更多相关文章

  1. GOOGLE地图坐标拾取方法、GOOGLE地图获取坐标方法

    方法一: 打开google地图-->查找目的地-->右键:此位置居中--> 打开IE浏览器(百度浏览器.GOOGLE浏览器.360浏览器均不行,只能在IE中获取),在IE浏览器的地址 ...

  2. MySQL新建用户保存的时报错:The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement

    又是这种错, 以前没遇过, 没办法, 直接google. 下面看解决办法: 登录mysql, 当然了如果您登录不上(密码错误情况), 直接扔这个属性进去my.cnf配置文件skip-grant-tab ...

  3. MySQL中删除重复数据的简单方法,mysql删除重复数据

    MYSQL里有五百万数据,但大多是重复的,真实的就180万,于是想怎样把这些重复的数据搞出来,在网上找了一圈,好多是用NOT IN这样的代码,这样效率很低,自己琢磨组合了一下,找到一个高效的处理方式, ...

  4. 检索Google Maps地图位置(小训练)

    名称:检索地图位置 内容:地图初期显示和检索显示 功能:根据条件检索地图的经度与纬度 1.在这之前我们需要创建一个表(Accoun__c),添加一个重要的字段地理位置情報,它会默认的给你两个字段经度和 ...

  5. Google Maps API V3 之绘图库 信息窗口

    Google官方教程: Google 地图 API V3 使用入门 Google 地图 API V3 针对移动设备进行开发 Google 地图 API V3 之事件 Google 地图 API V3 ...

  6. Google Maps API V3 之 图层

    Google官方教程: Google 地图 API V3 使用入门 Google 地图 API V3 针对移动设备进行开发 Google 地图 API V3 之事件 Google 地图 API V3 ...

  7. Google Maps API V3 之 路线服务

    Google官方教程: Google 地图 API V3 使用入门 Google 地图 API V3 针对移动设备进行开发 Google 地图 API V3 之事件 Google 地图 API V3 ...

  8. google map 点击获取经纬度

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. ☀【移动】Google Maps JavaScript API v3

    Google Maps JavaScript API v3https://developers.google.com/maps/documentation/javascript/tutorial?hl ...

随机推荐

  1. 手把手教你用深度学习做物体检测(五):YOLOv1介绍

    "之前写物体检测系列文章的时候说过,关于YOLO算法,会在后续的文章中介绍,然而,由于YOLO历经3个版本,其论文也有3篇,想全面的讲述清楚还是太难了,本周终于能够抽出时间写一些YOLO算法 ...

  2. NLP(十四) 情感分析

    情感在自然语言中的表达方式 例句 解释 I am very happy 开心的情感 She is so :( 表达悲伤的图标 import nltk import nltk.sentiment.sen ...

  3. HDU - 4009 - Transfer water 朱刘算法 +建立虚拟节点

    HDU - 4009:http://acm.hdu.edu.cn/showproblem.php?pid=4009 题意: 有n户人家住在山上,现在每户人家(x,y,z)都要解决供水的问题,他可以自己 ...

  4. 工程点点app爬虫和sign算法破解

    这世界真的什么人都有,哎,继续分析. 通过对工程点点的逆向和抓包分析,发现工程点点需要x-sign和token验证. this.b.a(aVar.b("Accept", " ...

  5. 使用Nginx、Nginx Plus防止服务器DDoS攻击

    分布式拒绝服务攻击(DDoS)指的是通过多台机器向一个服务或者网站发送大量看似合法的数据包使其网络阻塞.资源耗尽从而不能为正常用户提供正常服务的攻击手段.随着互联网带宽的增加和相关工具的不断发布,这种 ...

  6. 基于Selenium+Python的web自动化测试框架

    一.什么是Selenium? Selenium是一个基于浏览器的自动化测试工具,它提供了一种跨平台.跨浏览器的端到端的web自动化解决方案.Selenium主要包括三部分:Selenium IDE.S ...

  7. WS的发布与调用

    WebService—CXF整合Spring实现接口发布和调用过程  https://www.cnblogs.com/domi22/p/8094517.html   spring 集成cxf 第二弹( ...

  8. WPF 自定义UI控件学习

    最近项目中运用到了WPF处理三维软件,在C/S结构中WPF做UI还是有很多优越性,简单的学了一点WPF知识,成功的完成项目目标.项目过度阶段对于WPF的一些基本特点有了进一步了解 .至此花费一点时间研 ...

  9. Nginx安装及详解

    Nginx简介: Nginx(发音engine x)专为性能优化而开发的开源软件,是HTTP.反向代理.邮件代理.TCP/UDP协议代理软件,由俄罗斯的作者Igor Sysoev开发,其最知名的优点是 ...

  10. JAVASSM框架面试题

    1.SpringMVC的工作流程? 1. 用户发送请求至前端控制器DispatcherServlet 2. DispatcherServlet收到请求调用HandlerMapping处理器映射器. 3 ...