程序员各城市生存数据状况

liuyuhang原创,严禁转载!

电话&微信:13501043063

近期离开了北京回到老家,打算做一下程序员生存状况的调研,结合房价来进行一次分析,决定自己应该去哪座城市

于是便产生了此项目。

访问地址:http://www.piresume.com/ZhiLianDemo/workPosition/index.html

前端代码自己用浏览器扒,不贴了

注意:

目前的数据量并不是很庞大,只有北京的比较全面,一般单个岗位数据超过600个人认为才有参考价值,智联一次能访问的数据量大约在1200不到的样子。

数据更新中(每天只能更新2w条数据),预计一两个月以后该数据会比较充分,目前请自行识别数据样本的数量和可靠性

项目结果截屏:

章节目录:

一、项目思路

①在智联招聘网站上,能够根据get请求获取某个城市某关键字情况下的90*12个岗位数据,包括内容以及各式如下:

{"code": 200,"data": {"chatTotal": 0,"chatWindowState": 0,"count": 1000,"informationStream": null,"jobLabel": null,"method": "","typeSearch": 0,"results": [{"number": "CC223880420J00328951203","jobName": "web前端开发工程师","company": {"name": "四川中疗网络科技有限公司","number": "CZ223880420","type": {"name": "股份制企业"},"size": {"name": "20-99人"},"url": "https://company.zhaopin.com/CZ223880420.htm"},"city": {"items": [{"name": "成都","code": "801"}],"display": "成都"},"updateDate": "2019-07-12 11:27:19","salary": "7K-14K","distance": 0,"eduLevel": {"name": "大专"},"jobType": {"items": [{"name": "软件/互联网开发/系统集成"}]},"feedbackRation": 0.93,"workingExp": {"name": "3-5年"},"industry": "160000","emplType": "全职","applyType": "1","saleType": true,"positionURL": "https://jobs.zhaopin.com/CC223880420J00328951203.htm","companyLogo": "https://zhaopin-rd5-pub.oss-cn-beijing.aliyuncs.com/imgs/company/6ee298d97aef480d26c096b7827afa70.png","tags": [],"expandCount": 0,"score": "13","vipLevel": 1002,"positionLabel": "{\"qualifications\":null,\"role\":null,\"chatWindow\":null,\"refreshLevel\":0,\"skillLabel\":[{\"state\":0,\"value\":\"VUE\"},{\"state\":0,\"value\":\"Javascript\"},{\"state\":0,\"value\":\"Bootsrap\"}]}","welfare": ["餐补", "加班补助", "弹性工作", "带薪年假", "大牛带队"],"businessArea": "桐梓林","futureJob": false,"futureJobUrl": "","tagIntHighend": 0,"rootOrgId": 22388042,"staffId": 1037726905,"chatWindow": 0,"selected": false,"applied": false,"collected": false,"isShow": false,"timeState": "招聘中","rate": "93%"}, {
//以下各式相同,省略......

View Code

②在此内容中,包括该岗位的静态页面的请求地址,例如"positionURL": "https://jobs.zhaopin.com/CC223880420J00328951203.htm",

③在此地址中,若返回页面正常(非正常情况之后再说),则能从其中解析出该岗位的实际地理位置的文字描述。

④百度地图的jsAPI中有对地址的批量逆解析,获取到经纬度

⑤将获取的数据使用echarts呈现出来

二、获取数据中存在的问题

①智联对于xxs的攻击防御,是以ip来界定的,每个ip大约每分钟访问40次即无法正常访问获取想要的地址了。

②智联招聘对于频繁的访问有黑名单制度,可能是二级以上的黑名单:

  首先会有滑块验证

  然后会有403错误,EOF错误等

  智联招聘封禁的时间大概是5个小时左右

③智联招聘对于模仿浏览器登录,做了cookie防御,具体防御策略如下:

a.

b.

说明:

智联第一次登陆是没有cookie的,但是有个set-cookie字段的header信息,这个信息是通过浏览器直接修改cookie,而在header里,明确声明了禁止js修改cookie,也就是说,非浏览器无法将这个信息修改到cookie里去

而且,这个信息也是一个非常长的随机串,并且头内容也有很多不同,每次随机出现

在此刷新以后,上面的set-cookie字段要求的内容,就会出现在下一次请求的cookie里,这个不是通过js操作完成的

上面的header里有声明,path=httponly,就是只能通过浏览器的http协议的头信息操作该cookie

所以,这个绕不过去

而且,一旦acw_tc发现被模仿,他会更换头,比如更换成x-zp-client,或者其他的,就他在cookie里已经有的字段,会从头信息里拿出来,在此放进去,需要写的代码内容有点多,后来我都懒得写了

因为,即使你以此情况完成了头信息和cookie的设置,依然没法逃避xxs的每分钟40次访问数量限制,依然封ip,只是这个能逃避掉403错误,滑块验证而已

所以,干脆我就买了个代理池,暴力点

第一张图,第一次访问,header里有
acw_tc=2760822115643857462201201ef4938458f124a0f1146bb552fe88d24b01e7
第二次刷新,就在第二次请求的头信息里了,而头就没有了这个,如果第二次刷新,该ip没有将这个信息加入到cookie中,它就不会在发了

连续2-3次不发set-cookie,而cookie中又不带该信息,他会将这个ip返回403错误或者滑块验证

因为有如上问题存在,所以就必须要使用代理ip来爬取数据了。

关于什么是代理ip,代理的原理,自行百度

三、java爬取西刺代理ip池

笔者为了获取足够的数据来统计,节约时间(西刺代理每天的免费代理ip数量有限),购买了花生XX收费代理池...,但是最初还是用西刺代理做的测试

使用收费代理后,就不必在java代码中修改全局代理变量了,节约了不少代码

为了解决代理问题,第一印象是找收费代理ip池,然后想起来,免费的应该有,于是找到了西刺代理,emmm,既然有高匿代理,直接拿高匿代理的ip池吧

获取该ip池的部分重要代码如下:

①httpclient的代码:

package com.FM.tool;import java.io.File;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;/*** httpclient 发送get/post 请求* * @author YF02**/
public class HttpClientUtil {// utf-8字符编码public static final String CHARSET_UTF_8 = "utf-8";// HTTP内容类型。public static final String CONTENT_TYPE_TEXT_HTML = "text/xml";// HTTP内容类型。相当于form表单的形式,提交数据public static final String CONTENT_TYPE_FORM_URL = "application/x-www-form-urlencoded";// HTTP内容类型。相当于form表单的形式,提交数据public static final String CONTENT_TYPE_JSON_URL = "application/json;charset=utf-8";// 连接管理器private static PoolingHttpClientConnectionManager pool;// 请求配置private static RequestConfig requestConfig;static {try {//System.out.println("初始化HttpClientTest~~~开始");SSLContextBuilder builder = new SSLContextBuilder();builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());// 配置同时支持 HTTP 和 HTPPSRegistry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create().register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslsf).build();// 初始化连接管理器pool = new PoolingHttpClientConnectionManager(socketFactoryRegistry);// 将最大连接数增加到200,实际项目最好从配置文件中读取这个值pool.setMaxTotal(200);// 设置最大路由pool.setDefaultMaxPerRoute(2);// 根据默认超时限制初始化requestConfigint socketTimeout = 20000;int connectTimeout = 20000;int connectionRequestTimeout = 20000;requestConfig = RequestConfig.custom().setConnectionRequestTimeout(connectionRequestTimeout).setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();//System.out.println("初始化HttpClientTest~~~结束");} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (KeyStoreException e) {e.printStackTrace();} catch (KeyManagementException e) {e.printStackTrace();}// 设置请求超时时间requestConfig = RequestConfig.custom().setSocketTimeout(50000).setConnectTimeout(50000).setConnectionRequestTimeout(50000).build();}public static CloseableHttpClient getHttpClient() {CloseableHttpClient httpClient = HttpClients.custom()// 设置连接池管理
                .setConnectionManager(pool)// 设置请求配置
                .setDefaultRequestConfig(requestConfig)// 设置重试次数.setRetryHandler(new DefaultHttpRequestRetryHandler(0, false)).build();return httpClient;}/*** 发送Post请求* * @param httpPost* @return*/private static String sendHttpPost(HttpPost httpPost) {CloseableHttpClient httpClient = null;CloseableHttpResponse response = null;// 响应内容String responseContent = null;try {// 创建默认的httpClient实例.httpClient = getHttpClient();// 配置请求信息
            httpPost.setConfig(requestConfig);// 执行请求response = httpClient.execute(httpPost);// 得到响应实例HttpEntity entity = response.getEntity();// 可以获得响应头// Header[] headers = response.getHeaders(HttpHeaders.CONTENT_TYPE);// for (Header header : headers) {// System.out.println(header.getName());// }// 得到响应类型// System.out.println(ContentType.getOrDefault(response.getEntity()).getMimeType());// 判断响应状态if (response.getStatusLine().getStatusCode() >= 300) {throw new Exception("HTTP Request is not success, Response code is " + response.getStatusLine().getStatusCode());}if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {responseContent = EntityUtils.toString(entity, CHARSET_UTF_8);//关闭HttpEntity的流
                EntityUtils.consume(entity);}} catch (Exception e) {e.printStackTrace();} finally {try {// 释放资源if (response != null) {response.close();}} catch (IOException e) {e.printStackTrace();}}return responseContent;}/*** 发送Get请求* * @param httpGet* @return*/private static String sendHttpGet(HttpGet httpGet) {CloseableHttpClient httpClient = null;CloseableHttpResponse response = null;// 响应内容String responseContent = null;try {// 创建默认的httpClient实例.httpClient = getHttpClient();// 配置请求信息
            httpGet.setConfig(requestConfig);httpGet.addHeader("accept", "*/*");httpGet.addHeader("connection", "Keep-Alive");httpGet.addHeader("Content-Type", "application/json");httpGet.addHeader("user-agent", "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");//"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "//"Chrome/59.0.3071.115 Safari/537.36"// 发送POST请求必须设置如下两行//conn.setDoOutput(true);//conn.setDoInput(true);// 执行请求response = httpClient.execute(httpGet);// 得到响应实例HttpEntity entity = response.getEntity();// 可以获得响应头// Header[] headers = response.getHeaders(HttpHeaders.CONTENT_TYPE);// for (Header header : headers) {// System.out.println(header.getName());// }// 得到响应类型// System.out.println(ContentType.getOrDefault(response.getEntity()).getMimeType());// 判断响应状态if (response.getStatusLine().getStatusCode() >= 300) {throw new Exception("HTTP Request is not success, Response code is " + response.getStatusLine().getStatusCode());}if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {responseContent = EntityUtils.toString(entity, CHARSET_UTF_8);EntityUtils.consume(entity);}} catch (Exception e) {e.printStackTrace();} finally {try {// 释放资源if (response != null) {response.close();}} catch (IOException e) {e.printStackTrace();}}return responseContent;}/*** 发送 post请求* * @param httpUrl*            地址*/public static String sendHttpPost(String httpUrl) {// 创建httpPostHttpPost httpPost = new HttpPost(httpUrl);return sendHttpPost(httpPost);}/*** 发送 get请求* * @param httpUrl*/public static String sendHttpGet(String httpUrl) {// 创建get请求HttpGet httpGet = new HttpGet(httpUrl);return sendHttpGet(httpGet);}/*** 发送 post请求(带文件)* * @param httpUrl*            地址* @param maps*            参数* @param fileLists*            附件*/public static String sendHttpPost(String httpUrl, Map<String, String> maps, List<File> fileLists) {HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPostMultipartEntityBuilder meBuilder = MultipartEntityBuilder.create();if (maps != null) {for (String key : maps.keySet()) {meBuilder.addPart(key, new StringBody(maps.get(key), ContentType.TEXT_PLAIN));}}if (fileLists != null) {for (File file : fileLists) {FileBody fileBody = new FileBody(file);meBuilder.addPart("files", fileBody);}}HttpEntity reqEntity = meBuilder.build();httpPost.setEntity(reqEntity);return sendHttpPost(httpPost);}/*** 发送 post请求* * @param httpUrl*            地址* @param params*            参数(格式:key1=value1&key2=value2)* */public static String sendHttpPost(String httpUrl, String params) {HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPosttry {// 设置参数if (params != null && params.trim().length() > 0) {StringEntity stringEntity = new StringEntity(params, "UTF-8");stringEntity.setContentType(CONTENT_TYPE_FORM_URL);httpPost.setEntity(stringEntity);}} catch (Exception e) {e.printStackTrace();}return sendHttpPost(httpPost);}/*** 发送 post请求* * @param maps*            参数*/public static String sendHttpPost(String httpUrl, Map<String, String> maps) {String param = convertStringParamter(maps);return sendHttpPost(httpUrl, param);}/*** 发送 post请求 发送json数据* * @param httpUrl*            地址* @param paramsJson*            参数(格式 json)* */public static String sendHttpPostJson(String httpUrl, String paramsJson) {HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPosttry {// 设置参数if (paramsJson != null && paramsJson.trim().length() > 0) {StringEntity stringEntity = new StringEntity(paramsJson, "UTF-8");stringEntity.setContentType(CONTENT_TYPE_JSON_URL);httpPost.setEntity(stringEntity);}} catch (Exception e) {e.printStackTrace();}return sendHttpPost(httpPost);}/*** 发送 post请求 发送xml数据* * @param httpUrl   地址* @param paramsXml  参数(格式 Xml)* */public static String sendHttpPostXml(String httpUrl, String paramsXml) {HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPosttry {// 设置参数if (paramsXml != null && paramsXml.trim().length() > 0) {StringEntity stringEntity = new StringEntity(paramsXml, "UTF-8");stringEntity.setContentType(CONTENT_TYPE_TEXT_HTML);httpPost.setEntity(stringEntity);}} catch (Exception e) {e.printStackTrace();}return sendHttpPost(httpPost);}/*** 将map集合的键值对转化成:key1=value1&key2=value2 的形式* * @param parameterMap*            需要转化的键值对集合* @return 字符串*/public static String convertStringParamter(Map parameterMap) {StringBuffer parameterBuffer = new StringBuffer();if (parameterMap != null) {Iterator iterator = parameterMap.keySet().iterator();String key = null;String value = null;while (iterator.hasNext()) {key = (String) iterator.next();if (parameterMap.get(key) != null) {value = (String) parameterMap.get(key);} else {value = "";}parameterBuffer.append(key).append("=").append(value);if (iterator.hasNext()) {parameterBuffer.append("&");}}}return parameterBuffer.toString();}}

View Code

②获取西刺代理ip列表的代码:

/*** 获取免费的ips,该代理为西刺代理,注意此方法调用一定要有间隔,因为西刺代理也做了反爬措施* 若自身ip被封,无法打开西刺代理网页(通常返回403),则应断掉路由器的网络,重启后,运营商会重新分配一个ip地址,该地址应该可以继续访问* * @params:num为页面,每个页面大约五十个ip* @params:地址为https://www.xicidaili.com/nn/,使用高匿代理ip* @return:返回list,为host和prot的列表,从map中取*/public List getIps(Integer num) {StringBuffer buffer = new StringBuffer();buffer.append("https://www.xicidaili.com/nn/");//西祠代理地址if (null != num) {buffer.append("" + num);}String result = HttpClientUtil.sendHttpGet(buffer.toString());List<Integer> indexList = new ArrayList();List<Map<String, String>> hostAndPortList = new ArrayList();String indexFlag = "<img src=\"//fs.xicidaili.com/images/flag/cn.png\" alt=\"Cn\" /></td>";//在此之后的为ipint index = 0;// System.out.println(result);while (true) {int indexs = result.indexOf(indexFlag, index + 1);if (indexs > index) {indexList.add(indexs);index = indexs;} else {break;}}for (int i = 0; i < indexList.size(); i++) {String hostAndPort = result.substring(indexList.get(i) + indexFlag.length(),indexList.get(i) + indexFlag.length() + 55);Map temp = new HashMap();String host = hostAndPort;String port = hostAndPort;//获取hosttemp.put("host", host.substring(hostAndPort.indexOf("<td>") + 4, hostAndPort.indexOf("</td>")));//获取porttemp.put("port", port.substring(hostAndPort.lastIndexOf("<td>") + 4, hostAndPort.lastIndexOf("</td>")));hostAndPortList.add(temp);}System.out.println("获取代理ip成功,共计" + hostAndPortList.size() + "个ip");return hostAndPortList;}

View Code

四、java爬取智联岗位列表

获取智联的方位列表,还是相对容易的,只要拼接正确了url即可,该访问地址可在网页的控制台中看到

相关参数的解析,网上有的,不过多数都不用关心,本人获取该内容时候使用的请求代码如下:

/*** 将获取的智联列表页集中到一个map中* * @param keyWord* @param city* @return* @throws NoSuchAlgorithmException*/public ArrayList getListAllInZhiLian(String keyWord, String city) throws NoSuchAlgorithmException {ArrayList list = new ArrayList();for (int i = 0; i < 12; i++) {Map temp = getList(keyWord, city, i);list.add(temp);}return list;}/*** 获取智联每一个列表页,一共12页* * @param keyWord* @param city* @param page* @return* @throws NoSuchAlgorithmException*/public Map getList(String keyWord, String city, int page) throws NoSuchAlgorithmException {StringBuffer buffer = new StringBuffer();buffer.append("https://fe-api.zhaopin.com/c/i/sou?");if (page > 0) {buffer.append("&start=" + (90 * page));// 页数,最多12
        }buffer.append("&pageSize=90");// 单页数量buffer.append("&cityId=" + city);// 城市buffer.append("&workExperience=-1");// 工作经验buffer.append("&education=-1");// 学历buffer.append("&companyType=-1");// 企业类型buffer.append("&employmentType=-1");// ...buffer.append("&jobWelfareTag=-1");// ...buffer.append("&kw=" + keyWord);// 搜索关键词buffer.append("&kt=3");// ...buffer.append("&rt=e7e586269e414dd8a2906eb55808a780");// ...buffer.append("&_v=" + new Double(Math.random()).toString().substring(0, 10));// ...0.34575205随机9位小数String str = new Double(Math.random()).toString().substring(2, 10)+ new Double(Math.random()).toString().substring(2, 10)+ new Double(Math.random()).toString().substring(2, 10);MessageDigest md = MessageDigest.getInstance("MD5");md.update(str.getBytes());String mdStr = new BigInteger(1, md.digest()).toString(16);String time = new Long(new Date().getTime()).toString();String random = new Double(Math.random()).toString().substring(2, 8);buffer.append("&x-zp-page-request-id=" + mdStr + "-" + time + "-" + random);// 32位随机数md5加密+时间戳+6位随机数buffer.append("&x-zp-client-id=91a68428-2f82-47fc-aaa7-3056aeaf4062");// ...
String result = HttpClientUtil.sendHttpGet(buffer.toString());Map maps = (Map) JSON.parse(result);return maps;}

View Code

五、根据智联岗位列表获取该岗位工作地址

获取西刺代理池,并从智联获取列表,然后对列表中的页面地址获取,再从页面地址中解析,并存储到数据库中,其主要代码结构如下:

ArrayList list = getListAllInZhiLian((String) paramsSimple.get("keyWord"),(String) paramsSimple.get("city"));if (((String) paramsSimple.get("keyWord")).equals("") || ((String) paramsSimple.get("city")).equals("")) {resultMap.put("list", "没有输入关键字");resultMap.put("status", "error");resultMap.put("message", "城市或者关键字缺失");return resultMap;// 自动转换为json
            }System.out.println("尝试获取地址列表,共计" + list.size() + "个链接要查询");for (int i = 0; i < list.size(); i++) {List<Map<String, Object>> li = null;try {li = (List) ((Map) ((Map) list.get(i)).get("data")).get("results");} catch (Exception e2) {// e2.printStackTrace();System.out.println("li error may be null");}if (null != li && !li.isEmpty() && li.size() > 0) {System.out.println(li.size() + "个链接待查询");for (int j = 0; j < li.size(); j++) {// 验证该url是否已经存在于数据库中String positionUrl = (String) ((Map<String, Object>) li.get(j)).get("positionURL");Map paramCheck = new HashMap();paramCheck.put("positionUrl", positionUrl);session = sessionFactory.openSession();Map checkUrl = null;try {checkUrl = session.selectOne("com.FM.otherMapper.kwMapper.getJobByUrl", paramCheck);} catch (Exception e1) {// e1.printStackTrace();System.out.println("checkUrl error");}session.close();if (null == checkUrl) {String location = getPosition(positionUrl);if (null != location) {String loc = location.substring("<i class=\"iconfont icon-locate\"></i>".length());li.get(j).put("location", loc);Map<String, Object> param = new HashMap();param.put("companyName", ((Map) li.get(j).get("company")).get("name"));param.put("jobName", li.get(j).get("jobName"));param.put("keyWord", (String) paramsSimple.get("keyWord"));if (((String) li.get(j).get("salary")).contains("-")) {param.put("salaryLow",((String) li.get(j).get("salary")).split("-")[0].split("K")[0]);param.put("salaryTop",((String) li.get(j).get("salary")).split("-")[1].split("K")[0]);} else {param.put("salaryLow", 0);param.put("salaryTop", 0);}param.put("positionUrl", li.get(j).get("positionURL"));param.put("location", loc);param.put("workingExp", ((Map) li.get(j).get("workingExp")).get("name"));param.put("eduLevel", ((Map) li.get(j).get("eduLevel")).get("name"));param.put("emplType", li.get(j).get("emplType"));param.put("updateBy", new Date());param.put("x", "0");param.put("y", "0");param.put("city", (String) paramsSimple.get("city"));session = sessionFactory.openSession();try {session.insert("com.FM.otherMapper.kwMapper.createJob", param);System.out.println("url:" + positionUrl + "  地址:" + loc + "  存入数据库");} catch (Exception e) {// e.printStackTrace();System.out.println("insert error ");}session.close();}} else {System.out.println("url:" + positionUrl + "   已经在数据库中存在,跳过");}}} else {System.out.println("li中没有内容,获取具体列表失败");System.out.println(li);}System.out.println("90个拿完,继续!");}

View Code

对于该代码的触发方式,我是使用了springmvc,在一个页面中输入了city和key_word来触发的,后来进行了修改

六、工作地址逆解析

地址的解析,由百度来完成的,我对百度地图的jsAPI提供的逆解析示例进行了一定程度的修改,修改后的代码如下:

/**逆解析的触发函数*/function getGis() {$.ajax({type : 'POST',url : local + "KeyWord/getGis.do",//获取要逆解析的地址
            data : {},async : true,success : function(resultMap) {if (resultMap.status == 'success') {for (var i = 0; i < resultMap.gisList.length; i++) {updateGis(resultMap.gisList[i]);//循环逆解析列表中的每一个地址
                    }} else {console.error(resultMap)}console.log(resultMap)},error : function(resultMap) {console.error(resultMap)}});}//逆解析需要的对象var map = new BMap.Map("map0");var myGeo = new BMap.Geocoder();//逆解析调用的函数function updateGis(li) {geocodeSearch(li);}//百度逆解析的回调函数function geocodeSearch(li) {myGeo.getPoint(li.location, function(point) {if (point) {//console.log('id:' + li.id + '  x:' + point.lng + '  y:' + point.lat);li.x = point.lng;li.y = point.lat;console.log(li.id)modifyGis(li) //储存xy到数据库} else {console.log('error')}}, li.city);}/** 储存xy经纬度到数据库*/function modifyGis(li) {$.ajax({type : 'POST',url : local + "KeyWord/updateGis.do",data : {id : li.id,x : li.x,y : li.y,},async : true,success : function(resultMap) {//console.log(resultMap)
            },error : function(resultMap) {console.error(resultMap)}});}

View Code

七、数据统计与分析

如下地址可访问:

http://www.piresume.com/ZhiLianDemo/workPosition/index.html

以上!

转载于:https://www.cnblogs.com/liuyuhangCastle/p/11277024.html

程序员各城市生存数据状况相关推荐

  1. 4位超60岁程序员大爷的生存秘籍

    4位超60岁程序员大爷的生存秘籍 2017-05-04 浏览(11285) 评论(45) 想免费获取内部独家PPT资料库?观看行业大牛直播? 点击加入腾讯GAD游戏开发行业精英群 484290331 ...

  2. python的类程序的结构_Python程序员学习路径之数据结构篇

    原标题:Python程序员学习路径之数据结构篇 点击标题下「异步图书」可快速关注 在计算机科学中,数据结构是一门进阶性课程,概念抽象,难度较大.Python语言的语法简单,交互性强.用Python来讲 ...

  3. 越来越多的Java程序员转行Java大数据...

    JAVA的精密,强大,拥有其它语言不可替代的性能和可维护性,早已经是成为最受欢迎的编程语言之一,很多人想进入IT行业,首选的第一门语言就是JAVA. 但是,在未来肯定是大数据的天下,人工智能的爆发,将 ...

  4. 千锋好程序员与京东云大数据共建班,开班典礼在京东总部圆满举行

    近日,由千锋好程序员和京东云联合打造的大数据+数据智能共建班一经推出,便获得了学员的广泛认可,咨询和报名情况火爆,千锋教育全国分校陆续开班.继郑州分校首期班顺利开班,3月10日,千锋教育北京分校开班仪 ...

  5. 程序员的简历生存之道

    转载声明:商业转载请联系作者获得授权,非商业转载请注明出处.原文来自 © 呆萌钟 程序员的简历生存之道 前言 自从毕业以后到现在,自己投递的简历不在少数,工作期间也看了不少程序员的简历.再经历了从求职 ...

  6. 腾讯起诉vivo不正当竞争;链家程序员删除公司9TB数据被判7年;iPhone关机后仍在运行,或成恶意软件温床 | EA周报...

    EA周报 2022年5月20日 每个星期7分钟,元宝带你喝一杯IT人的浓缩咖啡,了解天下事.掌握IT核心技术. 周报看点 1.腾讯回应没有获得首批游戏版号,先让小公司回血更要紧 2.大厂一半以上程序员 ...

  7. 爬虫爬取黑马程序员论坛的网页数据

    #引入requests库 import requests #根据url发起请求,获取服务器响应文件 url:待抓取的url def load_page(url):#这里的请求头header可以是任意一 ...

  8. 2017年中国程序员调查分析:大数据就业前景广阔

    在互联网行业,程序员一直是很受关注的人群.特别对准备步入社会的大学生们来说,从事哪方面的职业是一个很重要的问题,而程序员就是一个比较热门的选择.大讲台老师根据2017年中国程序员调查的数据,给同学们好 ...

  9. 数据时代程序员必备技能:数据可视化

    说到数据可视化,大家可谓耳熟能详,设计师.数据分析师.数据科学家等,都用各种方式各种途径做着数据可视化的工作......实际上,我们每一个人,天生具有可视化思维,甚至经常性地做一些可视化操作. 比如, ...

最新文章

  1. python判断是否回文_对python判断是否回文数的实例详解
  2. python3 中 is, is not ,==, != 的区别
  3. 源码安装vlc播放器
  4. 聊天机器人中的深度学习技术(引言)
  5. C语言程序练习-L1-011 A-B (20分)
  6. 【Linux】一步一步学Linux——whereis命令(15)
  7. redis 判断存在性_springboot + redis + 注解 + 拦截器 实现接口幂等性校验
  8. encode_chunked=req.has_header(‘Transfer-encoding‘))问题解决方法
  9. 记一次服务器本地Tomcat能访问,但远程访问不了的解决方案
  10. LAMP/LNMP环境下:phpinfo php连接mysql php执行mysql查询 测试代码及响应
  11. Python2.x(3.x)安装及Ulipad的安装和使用
  12. ABAQUS常用量纲
  13. python写的ROS激光雷达扇形滤波
  14. FPGA学习杂记4——IP核简介、调用、复制和PLL IP核介绍
  15. Java,图片在table中显示并缩放2.0
  16. c++录屏、FFmpeg录屏、录屏格式转换
  17. 软件智能:aaas系统中AI的任务能力和工作
  18. 利用牛顿公式求解方程的根并且实现牛顿下山法
  19. Placement service – placement安装(wallaby-allinone)
  20. Python十分钟轻松入门

热门文章

  1. 华为ENSP中AR启动失败错误代码40,42,43,及启动后一直#的问题的一种解决方案
  2. 重学音视频?认识 MP4 视频(上)
  3. 黄河科技学院计算机信息中心,副校长杨龙一行赴黄河科技学院考察学习
  4. 【并发编程七】C++进程通信——套接字(socket)_80行代码实现一个聊天软件
  5. 新手入门 - 详解 frp 内网穿透 frpc.ini 配置
  6. eclipse 调试之异常断点
  7. 【NLP】Task2 数据读取与数据分析
  8. vue动态路由传参的几种方式
  9. 【Rust日报】 2019-03-31
  10. 【电子学会】2020年12月图形化四级 -- 绘制雪花