首發創作賽#
有粉絲經常私信于我,咨詢網絡爬蟲的技巧。網絡爬蟲,有許多現成的框架,每個框架都有優缺點。如果要精通網絡爬蟲,就需要有html和javascript知識的積累。如果沒有,就得學習,否則......其實網上也流傳著爬取城市空氣質量數據的方法的博客和文章,但是爬取的網站不同,方法也各異,有的不是爬取的權威網上的數據,來源也各異,具體數據來使用需要謹慎。
本人主要是想,通過不同案例,給粉絲展示不同網站爬取信息的應用技巧。本文章主要是向大家介紹,使用requests獲取權威網站公開發布的信息,不存在不能公開傳播的問題。并使用bs4解析爬取,城市AQI信息,即爬取AQI實時報和AQI日報?,F在整理出來分享給給大家。廢話不說了,直入主題。如果有不懂得地方,可以參考我以前寫的幾篇爬蟲文章。
目標網址:https://www.mee.gov.cn/
用瀏覽器打開https://www.mee.gov.cn/網站,如下圖所示:
將瀏覽器進入調試模式,如下圖所示。
分析其網頁html代碼,左邊紅框顯示的是AQI實時報和AQI日報的內容,右邊紅框顯示是對應的html的代碼。
<iframe id="indexKqZlIframe" scrolling="no" src="http://datacenter.mee.gov.cn/websjzx/homepages/airDatas.vm" frameborder="0" width="100%"></iframe>
需要指出的是:在進行爬取網站數據的時候,要有一定的html知識,這樣才能有效地分析網頁代碼。
IFRAME是HTML標簽,作用是文檔中的文檔,或者浮動的框架(FRAME)。iframe元素會創建包含另外一個文檔的內聯框架(即行內框架)。簡而言之,就是嵌套一個子網頁內容。
而這個網頁的內容的地址是:
http://datacenter.mee.gov.cn/websjzx/homepages/airDatas.vm。這是正確爬取全國城市空氣質量指數AQI至關重要的一步。
import requests
from bs4 import BeautifulSoup
除了網站的不同個,和我前面頭條的文章講過的一模一樣。
url='http://datacenter.mee.gov.cn/websjzx/homepages/airDatas.vm'
response=requests.get(url)
page=response.content.decode()
這個就不啰嗦了,我前面頭條的文章已經細講過了。
# 構建bs對象
soup=BeautifulSoup(page, 'html5lib')
通過分析網站返回的內容,AQI實時報和AQI日報的具體日期,如下圖紅色箭頭所示:
AQI實時報的具體日期,在id="tempdrhour"的<div></div>圖層中。
AQI日報的具體日期,在id="tempdrday"的<div></div>圖層中。
代碼如下:
#AQI實時報的具體日期
aqi_hour_date=soup.find(id='tempdrhour').text
#AQI日報的具體日期
aqi_day_date=soup.find(id='tempdrday').text
通過尋找id="tempdrhour"的text內容,得到AQI實時報的具體日期aqi_hour_date;
通過尋找id="tempdrday"的text內容,得到AQI實時報的具體日期aqi_day_date;
通過分析網站返回的內容,AQI實時報的具體內容在<table></table>的表格內容了。表體的id="legend_01_table",如下入紅色箭頭所示。
一個城市一行數據,其結構為<tr><td></td><td></td><td></td></tr>,根據這個特點,編寫代碼如下:
air_hour_content=soup.find(id='legend_01_table')
tr=air_hour_content.find_all('tr')
hour_citys=[]
hour_aqis=[]
hour_pollutions=[]
# 獲取AQI實時報的城市、AQI和首要污染物
for i in range(len(tr)):
td=tr[i].find_all('td')
city=td[0].text
aqi=td[1].text.strip()
pollution=td[2].text.strip()
hour_citys.append(city)
hour_aqis.append(aqi)
hour_pollutions.append(pollution)
首先,找到id='legend_01_table'的具體內容,然后find_all尋找所有的tr的內容,接著對每一行的tr的內容,find_all尋找所有的單元格td的內容,最后得到城市:hour_citys、AQI:hour_aqis和首要污染物:hour_pollutions。
通過分析網站返回的內容,AQII日報的具體內容在<table></table>的表格內容了。表體的id="legend_02_table",如下入紅色箭頭所示。
一個城市一行數據,其結構為<tr><td></td><td></td><td></td></tr>,根據這個特點,編寫代碼如下:
air_day_content=soup.find(id='legend_02_table')
tr=air_day_content.find_all('tr')
day_citys=[]
day_aqis=[]
day_pollutions=[]
# 獲取AQI日報的城市、AQI和首要污染物
for i in range(len(tr)):
td=tr[i].find_all('td')
city=td[0].text
aqi=td[1].text.strip()
pollution=td[2].text.strip()
day_citys.append(city)
day_aqis.append(aqi)
day_pollutions.append(pollution)
首先,找到id='legend_02_table'的具體內容,然后find_all尋找所有的tr的內容,接著對每一行的tr的內容,find_all尋找所有的單元格td的內容,最后得到城市:day_citys、AQI:day_aqis和首要污染物:day_pollutions。
保存AQI實時報數據,代碼如下:
file=open('aqi_hour.txt','w',encoding='UTF-8')
file.write(aqi_hour_date+'\n')
file.write('城市,AQI,首要污染物\n')
for i in range(len(hour_citys)):
file.write(hour_citys[i]+','+hour_aqis[i]+','+hour_pollutions[i]+"\n")
file.close()
AQI實時報數據保存在aqi_hour.txt中。
保存AQI日報數據,代碼如下:
file=open('aqi_day.txt','w',encoding='UTF-8')
file.write(aqi_day_date+'\n')
file.write('城市,AQI,首要污染物\n')
for i in range(len(day_citys)):
file.write(day_citys[i]+','+day_aqis[i]+','+day_pollutions[i]+"\n")
file.close()
AQI日報數據保存在aqi_day.txt中。
當然,你也可以根據業務場景的需要保存在數據庫中。這里我們就不另外討論了。
需要說明的是,aqi實時報的網站
http://datacenter.mee.gov.cn/websjzx/homepages/airDatas.vm,每個小時官方網站更新一次,你如果需要爬取每個小時的數據,就需要每隔一個小時爬取一次就OK了。
總結:通過網頁調試分析,正確識別提取全國城市空氣質量指數AQI的網址,然后利用requests獲取網頁代碼,接著用bs4進行分析,通過id識別表格內容和發布日期,最后獲取到有用信息后保存到文本文件。
載鏈接:https://juejin.im/post/5e7e126b51882573c508be13
最近在做一個類似支付寶口碑商家的功能模塊,其中有個功能就是計算出用戶與商家的距離,如下圖:
支付寶口碑商家頁面截圖
1、商家選取店鋪地址,將坐標經緯度存入數據庫;
2、移動端定位當前用戶坐標經緯度;
3、將商家經緯度從數據庫取出與當前用戶經緯度進行計算;
4、計算出的距離顯示在用戶端;
1、HTML5地理定位API;
2、百度地圖API;
1、在百度地圖開放平臺注冊開發者賬號;
2、登錄開發者賬號,在控制臺中創建應用,如下圖:
注意:移動web端的話,應用類型記得選擇瀏覽器端
注意:代碼中的ak="您的密鑰",記得換成控制臺中創建應用的AK密鑰
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
body, html{
width: 100%;
height: 100%;
margin:0;
font-family:"微軟雅黑";
font-size:14px;
}
#l-map{
height:300px;
width:100%;
}
#r-result{
width:100%;
}
</style>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=您的密鑰"></script>
<title>商家選取店鋪地址</title>
</head>
<body>
<div style="display: flex;">
<div style="width: 50%;height: 700px" id="l-map"></div>
<div style="width: 50%">
<div id="r-result">請輸入:<input type="text" id="suggestId" size="20" value="百度" style="width:150px;" /></div>
<div id="searchResultPanel" style="border:1px solid #C0C0C0;width:150px;height:auto; display:none;"></div>
</div>
</div>
</body>
</html>
<script type="text/javascript">
// 百度地圖API功能
function G(id) {
return document.getElementById(id);
}
var map=new BMap.Map("l-map");
map.centerAndZoom("北京",12); // 初始化地圖,設置城市和地圖級別。
var ac=new BMap.Autocomplete( //建立一個自動完成的對象
{"input" : "suggestId"
,"location" : map
});
var myValue;
ac.addEventListener("onconfirm", function(e) { //鼠標點擊下拉列表后的事件
var _value=e.item.value;
myValue=_value.province + _value.city + _value.district + _value.street + _value.business;
G("searchResultPanel").innerHTML="onconfirm<br />index=" + e.item.index + "<br />myValue=" + myValue;
setPlace();
});
function setPlace(){
map.clearOverlays(); //清除地圖上所有覆蓋物
function myFun(){
var pp=local.getResults().getPoi(0).point; //獲取第一個智能搜索的結果
map.centerAndZoom(pp, 18);
map.addOverlay(new BMap.Marker(pp)); //添加標注
}
var local=new BMap.LocalSearch(map, { //智能搜索
onSearchComplete: myFun
});
local.search(myValue);
}
//鼠標單擊獲取點擊的經緯度
map.addEventListener("click",function(e){
alert('該點擊區域的經緯度為:'+e.point.lng + "," + e.point.lat);//將該經緯度存入數據庫中
});
</script>復制代碼
seller.html運行效果圖如下:
注意1:由于HTML5地理定位僅限在移動端生效,因此user.html需要在移動端下運行(可將文件直接發送到手機上,在手機上打開運行)
注意2:代碼中的ak="您的密鑰",記得換成控制臺中創建應用的AK密鑰
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=您的密鑰"></script>
<title>計算用戶到商家的距離</title>
</head>
<body>
</body>
</html>
<script type="text/javascript">
//使用HTML5地理定位
function getLocation(){
//檢測瀏覽器是否支持地理定位
if (navigator.geolocation){
navigator.geolocation.getCurrentPosition(showPosition,showError);
//如果getCurrentPosition()運行成功,則向參數showPosition中規定的函數返回一個coordinates對象
//getCurrentPosition()方法的第二個參數showError用于處理錯誤。它規定當獲取用戶位置失敗時運行的函數
}else{
alert("該設備瀏覽器不支持地理定位");
}
}
function showPosition(position){
var Longitude=position.coords.longitude;//HTML5定位獲取的經度
var Latitude=position.coords.latitude;//HTML5定位獲取的緯度
//將HTML5定位獲取的經緯度,通過百度地圖API轉換成適應于百度定位的經緯度
var ggPoint=new BMap.Point(Longitude,Latitude);
//坐標轉換完之后的回調函數
translateCallback=function (data){
if(data.status===0) {
var map=new BMap.Map();
console.log(data.points[0]);//轉換后新的用戶經緯度
var pointA=new BMap.Point(data.points[0].lng,data.points[0].lat);//用戶的經緯度
var pointB=new BMap.Point(商家經度,商家緯度);//從數據庫中取出商家的經緯度
alert('您到商家的距離是:'+(map.getDistance(pointA,pointB)).toFixed(2)+' 米。'); //獲取兩點距離,保留小數點后兩位
}
}
var convertor=new BMap.Convertor();
var pointArr=[];
pointArr.push(ggPoint);
convertor.translate(pointArr, 1, 5, translateCallback)
}
function showError(error){
switch(error.code) {
case error.PERMISSION_DENIED:
alert("用戶不允許地理定位")
break;
case error.POSITION_UNAVAILABLE:
alert("無法獲取當前位置")
break;
case error.TIMEOUT:
alert("操作超時")
break;
case error.UNKNOWN_ERROR:
alert("未知錯誤")
break;
}
}
getLocation();
</script>復制代碼
user.html運行效果圖:
1、初次運行,詢問是否共享位置信息
2、點擊確認共享位置信息,彈出用戶與商家的距離
1、百度地圖API也可定位用戶的坐標經緯度,但是會出現偏移量,與實際位置相差很大,因此可使用HTML5地理定位用戶的原始坐標,再將原始坐標轉換成百度的定位坐標
2、由于HTML5地理定位僅限在移動端生效,因此使用HTML5地理定位需要在移動端下運行
覺得文章不錯的話,給我個關注哇,點個贊唄!
用場景:百度地圖的應用往往都是在網上的開放式應用,用戶在不同的城市,所以在地圖初始化的時候會希望不同用戶能夠加載自己當地的地圖。
下面給大家介紹兩種利用百度地圖API,在用戶打開瀏覽器頁面后自動初始化為用戶所在地區地圖的方法
根據IP定位用戶位置(每一臺連上網路的電腦都具有一個獨一無二的IP位址,經由IP位址可以反查出電腦位置,但是結果并不精確,而且很容易到受到ISP的IP分配機制影響,而造成誤差。本質上,LocalCity這個類是利用用戶IP地址去百度數據庫里查詢得到IP所在的城市。)
但是代碼非常的簡潔和方便,主要代碼如下:
<div id="allmap"></div>
<script type="text/javascript">
var map=new BMap.Map("allmap");
var myCity=new BMap.LocalCity();
myCity.get(myFun);
function myFun(result){
var cityName=result.name;
map.centerAndZoom(cityName,15);
setTimeout(function(){alert(cityName)},500);
}
</script>
運行效果如下:
2.Geolocation這個類是使用了支持HTML5瀏覽器提供的Geolocation API 來進行定位的。目前Internet Explorer 9、Firefox、Chrome、Safari 以及 Opera 支持地理定位(因為他們支持HTML5)。
<div id="allmap"></div>
<script type="text/javascript">
var map=new BMap.Map("allmap");
var point=new BMap.Point(116.331398,39.897445);
map.centerAndZoom(point,12);
var geolocation=new BMap.Geolocation(); //實例化瀏覽器定位對象。
geolocation.getCurrentPosition(function(r){ //定位結果對象會傳遞給r變量
if(this.getStatus()==BMAP_STATUS_SUCCESS){ //通過Geolocation類的getStatus()判斷定位結果
var mk=new BMap.Marker(r.point);
map.addOverlay(mk); //將marker作為覆蓋物添加到map地圖上
map.panTo(r.point); //移動地圖中心點到當前點
setTimeout(function(){ alert('您的位 置:'+r.point.lng+','+r.point.lat);},500);
}
else {alert('failed'+this.getStatus()); }
},{enableHighAccuracy: true}) //這個參數的含義就是 是否要求瀏覽器獲取最佳定位結果。
</script>
運行效果如下:
以上兩種方法大家可以根據自己的實際情況來使用,有問題也可以留言討論
*請認真填寫需求信息,我們會在24小時內與您取得聯系。