知识点
requests、BeautifulSoup、csv 等库的简单使用
高德地图 JavaScript API 的使用

1.安装需要的库:

sudo pip3 install --upgrade pip
sudo pip3 install bs4
sudo pip3 install lxml

用到三个文件:crawl.py、rent.csv与index.html,其中:

crawl.py 是一个非常简单的爬取网页的脚本。
rent.csv 由 crawl.py 生成,是房源文件。
index.html 是最重要的显示地图的部分。
实现的流程大致如下:

我为什么不把 js 代码和 css 代码从 index.html 中分出来呢,写脚本怎么顺手怎么来就好。

代码没有难度,主要就是看看几个 API 如何使用,下面给出文档链接:

高德 JavaScript API 帮助文档
高德 JavaScript API 示例中心
Requests: HTTP for Humans
Beautiful Soup 4.2.0 文档

本节将通过实践操作,带领大家利用高德 API 和 Python 解决租房问题。

注意:由于前端页面可能会经常发生变动,大家在这里主要掌握这种分析方法,如果页面发生了变化依然可以按照对应的方法进行爬取。

2.分析一下我们需要爬取的页面:https://bj.58.com/pinpaigongyu/。

选择好目标价位:

按 F12 键或右键点击检查分析元素:

我们发现所有的租房信息都是一个 li 标签,并且都位于 ul 标签下,当我们往下移的时候,相应的标签也会越来越多,所以我们便可以利用有无 list 类来判定是否为租房请求。当然,这是在没有任何条件获取到的全部信息,但很多信息我们是不会看的,既然有租房的意愿,那么我们就有一个大致的心理承受价格,因此我们可以来分析一下该网站的 url 构造形式,大致了解了它的路径规则:/pingpaigongyu/pn/{page}/minprice={min_rent}_{max_rent}

看一下页面能够提供给我们什么信息:

框框圈出的信息对我们来说已经足够了,点进去后还可以查看其他各类信息:

这些信息有些是经过了加密,并不一定准确,然后我们就可以根据以上信息来写一个小的爬虫程序。

创建 crawl.py 文件,这里先直接给出全部代码。

#!/usr/bin/env python3
from bs4 import BeautifulSoup # 网页解析模块
import requests # 网络请求模块
import csv # csv 文件模块
import time
import lxml
# 网址
url = "https://bj.58.com/pinpaigongyu/pn/{page}/?minprice=2000_4000"# 初始化页码
page = 0
# 打开rent.csv文件,如果没有就创建一个,并设置写入模式
csv_file = open("rent.csv","w",encoding="utf-8")
# 创建writer对象
csv_writer = csv.writer(csv_file, delimiter=',')
# 循环所有页面
while True:page += 1print("fetch: ", url.format(page=page))time.sleep(1)# 抓取目标页面response = requests.get(url.format(page=page))# 设置编码模式response.encoding = 'utf-8'# 创建一个BeautifulSoup对象,获取页面正文html = BeautifulSoup(response.text,features="lxml")# 获取当前页面的房子信息house_list = html.select(".list > li")# 循环在读不到新的房源时结束if not house_list:break# 房子信息for house in house_list:# 获取房子标题house_title = house.select("h2")[0].string# 获取房子链接地址house_url = house.select("a")[0]["href"]# 对标题进行分隔house_info_list = house_title.split()# 如果第二列是公寓名则取第一列作为地址if "公寓" in house_info_list[1] or "青年社区" in house_info_list[1]:house_location = house_info_list[0]else:house_location = house_info_list[1]house_money = house.select(".money")[0].select("b")[0].string# 写入一行数据csv_writer.writerow([house_title, house_location, house_money, house_url])# 关闭文件
csv_file.close()

鉴于爬的量不大所以就简单处理了。代码中已经给出了大部分注释,这里只对requests、BeautifulSoup、csv 库的使用进行说明:

csv 一般用作表格文件,直接用文本编辑器打开也可读,行与行之间就是换行来隔开,列与列之间就是用逗号(也可指定其它字符)隔开,Python 标准库中的 csv 库就是用来读写 csv 文件的。

requests 是一个对使用者非常友好的 http 库,看一遍 Quickstart 就能基本掌握它的使用。

用到它的地方也就仅仅两句:

# 抓取目标页面
response = requests.get(url.format(page=page))
# 获取页面正文
response.text

Beautiful Soup 是一个用来解析 html 或者 xml 文件的库,支持元素选择器,使用起来也非常方便:

# 创建一个 BeautifulSoup 对象
html = BeautifulSoup(response.text,features="lxml")# 获取 class=list 的元素下的所有 li 元素
house_list = html.select(".list > li")# 得到标签包裹着的文本
house.select("h2")[0].string
# 得到标签内属性的值
house.select("a")[0]["href"]

由于该网站设置了反爬虫机制非常容易被屏蔽。因此在每次爬取页面时使用 time.sleep(1),1 代表 1 秒。讲解完毕,运行代码 python3 crawl.py。注意如果是非会员在实验环境中不能联网,执行爬取的操作大家可以在本地进行)。等执行完毕查看目录会发现已经生成了 rent.csv 文件:

因为反爬虫以及数据加密的原因所以数据可能是乱码的,大家可以使用这个文件继续接下来的实验。

wget https://labfile.oss.aliyuncs.com/courses/599/rent.csv

后面我们需要从本地导入这个文件,大家需要下载这个文件到本地。

页面大框架可直接从示例中心复制:高德 JavaScript API 示例中心。

在 /home/project 目录下新建 index.html 复制粘贴下面的设计页面代码:

<html><head><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><metaname="viewport"content="initial-scale=1.0, user-scalable=no, width=device-width"/><title>毕业生租房</title><linkrel="stylesheet"href="http://cache.amap.com/lbs/static/main1119.css"/><linkrel="stylesheet"href="http://cache.amap.com/lbs/static/jquery.range.css"/><script src="http://cache.amap.com/lbs/static/jquery-1.9.1.js"></script><script src="http://cache.amap.com/lbs/static/es5.min.js"></script><script src="http://webapi.amap.com/maps?v=1.3&key=36aa77404a1c2f2fc922a569eaa49422&plugin=AMap.ArrivalRange,AMap.Scale,AMap.Geocoder,AMap.Transfer,AMap.Autocomplete"></script><script src="http://cache.amap.com/lbs/static/jquery.range.js"></script><style>/*面板控制样式*/.control-panel {position: absolute;top: 30px;right: 20px;}/*面板内容样式*/.control-entry {width: 280px;background-color: rgba(119, 136, 153, 0.8);font-family: fantasy, sans-serif;text-align: left;color: white;overflow: auto;padding: 10px;margin-bottom: 10px;}/*文字与右侧的距离*/.control-input {margin-left: 120px;}/*输入框宽度*/.control-input input[type='text'] {width: 160px;}/*文字样式*/.control-panel label {float: left;width: 120px;}/*路线规划信息窗体样式*/#transfer-panel {position: absolute;background-color: white;max-height: 80%;overflow-y: auto;top: 30px;left: 20px;width: 250px;}</style></head><body><div id="container"></div><!--显示输入地址面板--><div class="control-panel"><div class="control-entry"><label>选择工作地点:</label><div class="control-input"><input id="work-location" type="text" /></div></div><!--显示选择交通的面板--><div class="control-entry"><label>选择通勤方式:</label><div class="control-input"><inputtype="radio"name="vehicle"value="SUBWAY,BUS"onClick="takeBus(this)"checked/>公交+地铁<inputtype="radio"name="vehicle"value="SUBWAY"onClick="takeSubway(this)"/>地铁</div></div><!--显示导入房源的面板--><div class="control-entry"><label>导入房源文件:</label><div class="control-input"><input type="file" name="file" onChange="importRentInfo(this)" /></div></div></div><div id="transfer-panel"></div><script>//地图部分var map = new AMap.Map('container', {resizeEnable: true, //页面可调整大小zoomEnable: true, //可缩放center: [116.397428, 39.90923], //地图中心,这里使用的是北京的经纬度zoom: 11, //缩放等级,数字越大离地球越近});</script></body>
</html>
copy

讲解一下部分代码:

这一句中你会看到 key 这个参数,它需要你注册高德的开发者用户,创建应用才能得到,由于 JS API 不像它家的 Web API 一样有流量限制,所以这个 key 大可随意使用。

<script src="http://webapi.amap.com/maps?v=1.3&key=36aa77404a1c2f2fc922a569eaa49422&plugin=AMap.ArrivalRange,AMap.Scale,AMap.Geocoder,AMap.Transfer,AMap.Autocomplete"></script>

接下来我们简单的介绍一下如何注册高德地图的 key。

第一步:登录高德地图,点击右上角进行登录。

第二步:完善资料,包括开发者认证,邮箱认证,电话认证等,如实填写即可,由于认证比较简单,就不贴图了。

第三步:点击右上角控制台,创建应用,应用信息根据自己的实际填写即可。

第四步:创建完应用后点击右上角的“+”号就可以创建应用的 Key,使用地图是根据开发文档把相应位置的 key 值换成自己的就好了。

第五步:只需要根据开发文档把相应的 JS 引入项目,把你的 key 填写就可以了。

<script src="http://webapi.amap.com/maps?v=1.3&key=你的key值&plugin=AMap.ArrivalRange,AMap.Scale,AMap.Geocoder,AMap.Transfer,AMap.Autocomplete"></script>

载入编写代码时可能用到的 API 插件:

<script src="http://webapi.amap.com/maps?v=1.3&key=36aa77404a1c2f2fc922a569eaa49422&plugin=AMap.ArrivalRange,AMap.Scale,AMap.Geocoder,AMap.Transfer,AMap.Autocomplete"></script>

从名字就可以看出插件的作用:

ArrivalRange:公交到达圈。
Scale:标尺。
Geocoder:正向地理编码(地址-坐标)。
Transfer:路径规划。
Autocomplete:地址自动补全。
这些都可以在示例中心找到对应的例子:高德地图示例中心。

在输入标签内可以设定 onClick 与 onChange 属性,它们的作用是当该输入元素上发生点击或者内容变化的事件时,设定的内容就会被运行。

<inputtype="radio"name="vehicle"value="SUBWAY,BUS"onClick="takeBus(this)"checked
/>
<input type="file" name="file" onChange="importRentInfo(this)" />

control-panel 就是右上角的输入面板区域。transfer-panel 是路径规划面板,它只有在调用了路径规划的函数时才会出现。

<div class="control-panel"><div id="transfer-panel"></div>
</div>

输入 python3 -m http.server 8080 打开服务器,浏览器访问 http://localhost:8080 查看效果。

这个时候你发现页面里面没有地图,这是为什么呢?打开控制台看报错信息:

这是因为 https 页面里动态的引入 http 资源,比如引入一个 JS 文件,会被直接 block 掉的,在 https 页面里通过 AJAX 的方式请求 http 资源,也会被直接 block 掉的。解决办法是,在页面的 head 标签中加入:

<metahttp-equiv="Content-Security-Policy"content="upgrade-insecure-requests"
/>

意思是自动将 http 的不安全请求升级为 https。当然你也可以直接把 http 修改成 https,这里只是分享一下遇到的 bug 以及解决方法。

最终效果:

高德这套 API 只要逛逛示例中心,示例中心没有的就去看看参考手册,基本就够用了。接着上一节 index.html 里 script 的内容:

var map = new AMap.Map('container', {resizeEnable: true,zoomEnable: true,center: [116.397428, 39.90923],zoom: 11,
});
//添加标尺
var scale = new AMap.Scale();
map.addControl(scale);
//经度、纬度、时间、通勤方式(默认是地铁+公交)
var arrivalRange = new AMap.ArrivalRange();
var x,y,t,vehicle = 'SUBWAY,BUS';
//工作地点,工作标记
var workAddress, workMarker;
//房源标记数组
var rentMarkerArray = [];
//多边形数组,存储到达范围的计算结果
var polygonArray = [];
//路线规划
var amapTransfer;
//信息窗体对象
var infoWindow = new AMap.InfoWindow({offset: new AMap.Pixel(0, -30),
});
//地址自动补全对象
var auto = new AMap.Autocomplete({input: 'work-location',
});
//添加事件监听,在选择完地址后调用workLocationSelected
AMap.event.addListener(auto, 'select', workLocationSelected);function takeBus(radio) {vehicle = radio.value;loadWorkLocation();
}function takeSubway(radio) {vehicle = radio.value;loadWorkLocation();
}
//导入房源信息触发的方法
function importRentInfo(fileInfo) {//获取房源文件名称var file = fileInfo.files[0].name;loadRentLocationByFile(file);
}
//选择工作地点后触发的方法
function workLocationSelected(e) {//更新工作地点,加载到达范围workAddress = e.poi.name;//调用加载1小时到达区域的方法loadWorkLocation();
}
//加载工作地点标记
function loadWorkMarker(x, y, locationName) {workMarker = new AMap.Marker({map: map,title: locationName,icon: 'http://webapi.amap.com/theme/v1.3/markers/n/mark_r.png',position: [x, y],});
}
//加载到达范围
function loadWorkRange(x, y, t, color, v) {arrivalRange.search([x, y],t,function (status, result) {if (result.bounds) {for (var i = 0; i < result.bounds.length; i++) {//多边形对象var polygon = new AMap.Polygon({map: map,fillColor: color, //填充色fillOpacity: '0.4', //透明度strokeColor: color,strokeOpacity: '0.8',strokeWeight: 1, //线宽});//到达范围的多边形路径polygon.setPath(result.bounds[i]);//增加多边形polygonArray.push(polygon);}}},{policy: v,});
}
//添加房源标记
function addMarkerByAddress(address) {//地理编码对象var geocoder = new AMap.Geocoder({city: '北京',radius: 1000,});//获取位置geocoder.getLocation(address, function (status, result) {if (status === 'complete' && result.info === 'OK') {//获取地理编码var geocode = result.geocodes[0];//标记对象rentMarker = new AMap.Marker({map: map, //显示标记的地图title: address, //鼠标移动至标记时所显示的文字//标记图标地址icon: 'http://webapi.amap.com/theme/v1.3/markers/n/mark_b.png',//位置position: [geocode.location.getLng(), geocode.location.getLat()],});rentMarkerArray.push(rentMarker);//相关房源网络地址rentMarker.content ="<div>房源:<a target = '_blank' href='https://bj.58.com/pinpaigongyu/?key=" +address +"'>" +address +'</a><div>';//标记的事件处理rentMarker.on('click', function (e) {//设置信息窗体显示的内容infoWindow.setContent(e.target.content);infoWindow.open(map, e.target.getPosition());//路线规划是否清除if (amapTransfer) amapTransfer.clear();//换乘对象amapTransfer = new AMap.Transfer({map: map,policy: AMap.TransferPolicy.LEAST_TIME,city: '北京市',panel: 'transfer-panel',});//根据起、终点坐标查询换乘路线amapTransfer.search([{keyword: workAddress,},{keyword: address,},],function (status, result) {});});}});
}
//清除已有的到达区域
function delWorkLocation() {if (polygonArray) map.remove(polygonArray);if (workMarker) map.remove(workMarker);polygonArray = [];
}
//清除现有的房源标记
function delRentLocation() {if (rentMarkerArray) map.remove(rentMarkerArray);rentMarkerArray = [];
}
//加载1小时到达区域
function loadWorkLocation() {//清除已有的到达区域delWorkLocation();//创建地址坐标对象var geocoder = new AMap.Geocoder({city: '北京',radius: 1000,});//获取位置geocoder.getLocation(workAddress, function (status, result) {if (status === 'complete' && result.info === 'OK') {var geocode = result.geocodes[0]; //获取地址编码x = geocode.location.getLng(); //经度y = geocode.location.getLat(); //纬度//加载工作地点标记loadWorkMarker(x, y);//加载工作地点1小时内到达的范围loadWorkRange(x, y, 60, '#3f67a5', vehicle);//地图移动到工作地点的位置map.setZoomAndCenter(12, [x, y]);}});
}
//加载房源位置
function loadRentLocationByFile(fileName) {//清除现有的房源标记delRentLocation();//所有的地点都记录在集合中var rent_locations = new Set();//获取文件中的房源信息$.get(fileName, function (data) {//分割信息data = data.split('\n');//遍历房源位置data.forEach(function (item, index) {rent_locations.add(item.split(',')[1]);});rent_locations.forEach(function (element, index) {//加上房源标记addMarkerByAddress(element);});});
}

代码中已经给出了大部分注释,这里对小部分进行特别说明:

添加标尺,参考带功能控件的地图。

var scale = new AMap.Scale();
map.addControl(scale);

一些需要放到全局的变量:

//公交到达圈对象
var arrivalRange = new AMap.ArrivalRange();
//经度,纬度,时间(用不到),通勤方式(默认是地铁+公交)
var x,y,t,vehicle = 'SUBWAY,BUS';
//工作地点,工作标记
var workAddress, workMarker;
//房源标记队列
var rentMarkerArray = [];
//多边形队列,存储公交到达的计算结果
var polygonArray = [];
//路径规划
var amapTransfer;

信息窗体的使用,在房源标记被点击时弹出,参考给多个点添加信息窗体。

//信息窗体对象
var infoWindow = new AMap.InfoWindow({offset: new AMap.Pixel(0, -30),
});
//在房源标记被点击时打开
rentMarker.on('click', function (e) {//鼠标移到标记上会显示标记content属性的内容infoWindow.setContent(e.target.content);//在标记的位置打开窗体infoWindow.open(map, e.target.getPosition());
});

地址补完的使用,参考输入提示后查询。

var auto = new AMap.Autocomplete({//通过id指定输入元素input: 'work-location',
});
//添加事件监听,在选择补完的地址后调用workLocationSelected
AMap.event.addListener(auto, 'select', workLocationSelected);
copy
function workLocationSelected(e) {//更新工作地点,加载公交到达圈workAddress = e.poi.name;loadWorkLocation();
}

loadWorkLocation 的实现,这部分包含了地理编码的内容,参考正向地理编码(地址-坐标)。

function loadWorkLocation() {//首先清空地图上已有的到达圈delWorkLocation();var geocoder = new AMap.Geocoder({city: '北京',radius: 1000,});geocoder.getLocation(workAddress, function (status, result) {if (status === 'complete' && result.info === 'OK') {var geocode = result.geocodes[0];x = geocode.location.getLng();y = geocode.location.getLat();//加载工作地点标记loadWorkMarker(x, y);//加载60分钟内工作地点到达圈loadWorkRange(x, y, 60, '#3f67a5', vehicle);//地图移动到工作地点的位置map.setZoomAndCenter(12, [x, y]);}});
}

loadWorkRange 的实现,在地图上绘制到达圈,参考:公交到达圈。

function loadWorkRange(x, y, t, color, v) {arrivalRange.search([x, y],t,function (status, result) {if (result.bounds) {for (var i = 0; i < result.bounds.length; i++) {//新建多边形对象var polygon = new AMap.Polygon({map: map,fillColor: color,fillOpacity: '0.4',strokeColor: color,strokeOpacity: '0.8',strokeWeight: 1,});//得到到达圈的多边形路径polygon.setPath(result.bounds[i]);polygonArray.push(polygon);}}},{policy: v,});
}

载入房源信息功能的实现。由于安全问题,浏览器想要得到文件在系统内的位置就得用上一些技巧,这里还是算了,偷一下懒,因为房源文件跟 index.html 在同一个文件夹下,所以我们只要得到文件名就足够了。

function importRentInfo(fileInfo) {var file = fileInfo.files[0].name;loadRentLocationByFile(file);
}

我们使用一个集合来记录所有的房源地址。

function loadRentLocationByFile(fileName) {//先删除现有的房源标记delRentLocation();//所有的地点都记录在集合中var rent_locations = new Set();//jquery操作$.get(fileName, function (data) {data = data.split('\n');data.forEach(function (item, index) {rent_locations.add(item.split(',')[1]);});rent_locations.forEach(function (element, index) {//加上房源标记addMarkerByAddress(element);});});
}

addMarkerByAddress 的实现参考:按起终点名称规划路线与点标记。

注意其中这一句会被显示在信息窗体上。链接指向 58 品牌公寓馆的搜索页面,搜索的地址就是点标记(房源)的地址:

rentMarker.content ="<div>房源:<a target = '_blank' href='https://bj.58.com/pinpaigongyu/?key=" +address +"'>" +address +'</a><div>';

可直接下载最终代码使用:

wget https://labfile.oss.aliyuncs.com/courses/599/index.html

输入 python3 -m http.server 8080 打开服务器,浏览器访问 http://localhost:8080 查看效果。

首先选择工作地点:

划出了一小时内的通勤范围:

导入房源文件:

导入后:

选择一处房源,会自动帮你规划路径:

选中房源地址跳转到目标页面:

Python 实现高德地图找房相关推荐

  1. 高德地图找房 # 编程大实践 # Python # 嵩天 # cilay

    高德地图找房 一.项目背景 1.高德开放平台 高德开放平台是国内技术领先的LBS服务提供商,拥有先进的数据融合技术和海量的数据处理能力. 服务超过三十万款移动应用,日均处理定位请求及路径规划数百亿次. ...

  2. python + 高德地图API实现地图找房

    python + 高德地图API实现地图找房 项目简介:根据工作地点信息和58同城爬取的租房信息,通过高德地图进行显示,同时利用高德API自动规划房源到工作地点的通勤路线(公交+地铁) 项目仓库:ht ...

  3. 使用vue和高德地图,仿58地图找房pc端,且解决marker过多卡顿

    使用vue和高德地图,仿58地图找房pc端,且解决marker过多卡顿 1.在index.html引入高德地图链接 https://webapi.amap.com/maps?v=1.4.15& ...

  4. 你还在为高德地图找不到门牌号等详细地址而烦恼吗?你还在等什么——Python调用高德地图API实现经纬度换算、地图可视化

    Python调用高德地图API实现经纬度换算.地图可视化 前地图可视化的工具和函数比较多,但是在不知道相关地点经纬度的情况下,通过python调用高德地图API实现经纬度换算,并且直接在高德地图新推出 ...

  5. python爬取贝壳找房之北京二手房源信息

    所用库 requests xpath解析库 multiprocessing多进程 pandas库用于保存csv文件 实战背景 本文首发于:python爬取贝壳找房之北京二手房源信息 主要是为了做北京二 ...

  6. Java开发导入腾讯地图描点_腾讯地图点聚合开发-实现地图找房功能

    链家实现的效果 分析 链家的地图找房主要分为三层.第一层为市区层,比如南山.罗湖等:第二层为片区,比如南头.科技园等:第三层则为小区. 因为第一层,第二层的数据没有那么多,这两个接口都是把所有的数据一 ...

  7. 百度地图——地图找房功能

            代码地址:https://github.com/huiyan-fe/BMapGLLib  HouseSearchService层 package cn.itcast.baidumap. ...

  8. Python调用高德地图API实现经纬度换算、地图可视化

    作者 | 糖甜甜甜 出品 | 经管人学数据分析 Python调用高德地图API实现经纬度换算.地图可视化 前地图可视化的工具和函数比较多,但是在不知道相关地点经纬度的情况下,通过python调用高德地 ...

  9. 腾讯地图实现地图找房功能

    链家实现的效果 最近接到一个需求,需要使用鹅厂地图实现类似链家网的地图找房功能,然后我去网上看了一下,基本上使用的都是百度地图.于是我打算自己稍微封装一下,可以在使用的时候更加的方便. 01. 分析 ...

最新文章

  1. 【MyBatis】MyBatis分页插件PageHelper的使用
  2. REST架构下,浏览器怎么发送put与delete请求?
  3. C++静态联编与动态联编
  4. 商城系统学习总结(1)——订单与库存在高并发场景下案例解析
  5. 资源丨用PyTorch实现Mask R-CNN
  6. 《马化腾:领跑互联网》— 综合素质提升书籍
  7. Python中用冒号表达式对列表切片
  8. bootdo jar 改war 坑
  9. php会员代码大全,PHP在线获取VIP会员账号API接口代码
  10. 团队组成五个基本要素_团队构成的五大要素
  11. 如何在linux系统下的抓包文件保存在u盘里,在xp系统中打开,【Linux】Wireshark在Linux系统下的安装及使用...
  12. session保存和清除cookies
  13. android实现延时的方法,Android实现延时总结
  14. JavaScript学习第十九天
  15. 同时使用scanf()函数和getchar()函数无法输入字符串的问题
  16. 数据库sql简单的优化方案
  17. 尚硅谷大数据Hadoop(26)P100-P104编写Reduce类型,,WordCounter,运行,程序调试
  18. 如何完全卸载oracle
  19. java实现“两数之和”
  20. oracle如何删除重复数据保留第一条记录

热门文章

  1. Python批量获取基金数据
  2. 线性规划与网络流24题 2太空飞行计划问题 最大权闭合图问题(不懂) nefu 476
  3. python实现微信医院挂号查询,并钉钉实时通知
  4. 59.【初识JFrame和数据库——聊天系统】
  5. CamstarPortal操作记录(新建用户,设置菜单,创建产品流程)
  6. 解决udp socket报socketException使得服务端不再正常工作
  7. 有没有自动打码的软件
  8. 牌型种数【蓝桥杯真题】
  9. CentOS7部署Subversion服务器和TortoiseSVN客户端简记
  10. Ubuntu下Qemu安装Debian Mipsel