一、问题说明
现有一个任务需要对一个网站的城市做一些统计,并提取出这个网站上的城市的经纬度信息然后绘制在百度地图上。如果是一些数量不多的城市那也到好办,但是如果对于这种存在几百上千的城市,而且这些城市的经纬度信息在第三级网站上才能找到,这样一来,如果人工去完成会非常枯燥而且耗时长。
这个网站是维基百科关于
这里可以看到城市这一列是有超链接的,通过点击这个城市的超链接,进入到第二级网站上:
比如上面是我点击第一个城市的跳转,我们需要的信息在右上角,但是真正的经纬度的坐标其实在这个右上角的超链接里。继续点击:
进入到第三极网站,这里是我们需要的数据,经度和纬度。
我们需要对近400个站点做三个点击,然后复制这些数据,最后把这经度和纬度数据存储在json格式的数据里面,我们才能在前端的Js中进行读取,并使用百度地图显示。
二、解决办法
对于这种重复性的劳动,当然是想到利用之前自己研究了一阵子的爬虫进行解决。
可以参照之前的对于
第一步
我们的工作,首先最初的母网站是,
# -*-coding:utf-8 -*-
from urllib2 import urlopen #引入urllib2下的urlopen类,这个类可以对url进行操作,打开一个url链接
resp=urlopen('https://en.wikipedia.org/wiki/List_of_bicycle-sharing_systems#Cities')
html_data=resp.read().decode('utf-8')
print (html_data)
#接上面代码
from bs4 import BeautifulSoup as bs
soup=bs(html_data,'html.parser')#将读取到的网页代码用指定解析器html.parser进行解析
1
2
3
4
5
6
7
8
9
10
第二步
在这个网站上找到这个城市表,在此基础上进行超链接的两次点击进入。
首先是找到这个网站的 源代码,找到我们要的城市表
data_tables=soup.find_all('table')#通过soup对解析后的网页进行特定标签的读取,读取所有table
print data_tables[1]#这里找到了第一个table是我们想要的数据
1
2
这里的代码输出是:
刚好就是我们找到的源代码。完全符合
第三步
我们要的是a标签下的链接,才能二次进入网站
#除去第一行的表头,第一行有效数据里面选取第一个td里面的a标签下的链接
td_lists=sortable_list[1].find_all('td')
print td_lists[0]
a_lists=td_lists[0].find_all('a')
print a_lists[0]['href'],a_lists[0]['title']
1
2
3
4
5
第四步
#上面只是我们需要的数据的测试,下面开始写循环,提取上面的所有有用的数据_city
city_data_table=data_tables[1]#选取下标为1的table
citys_url_data=[]
#除去第一行表头,从i=1开始提取数据
for i in range(1,len(sortable_list)-1):
if i==229:
continue
if i==369:
continue
all_tr_data=sortable_list[i]
# print all_tr_data
# break
td_lists=all_tr_data.find_all('td')
a_lists=td_lists[0].find_all('a')#选取第一个td
one={}
print i,a_lists[0]['href'],a_lists[0]['title']
one['href']=a_lists[0]['href']
one['city']=a_lists[0]['title']
citys_url_data.append(one)
print citys_url_data
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
输出:
第五步
第一个方法,目的在于根据城市链接,进入到第二级网站,找到a标签,如图所示:
from bs4 import BeautifulSoup as bs
# 方法,目的在于根据城市的链接,进入到下一级的网站,并寻找到我们要的第二级的链接a标签
def get_url_data(url):
resp=urlopen(url)
html_data=resp.read().decode('utf-8')
# print (html_data)
soup=bs(html_data,'html.parser')#将读取到的网页代码用指定解析器html.parser进行解析
tr_datas=soup.find_all('span',id='coordinates')#通过soup对解析后的网页进行特定标签的读取,读取所有tr
if tr_datas==None:
return
# print tr_datas[0]#这里找到了第一个table是我们想要的数据
a_find=tr_datas[0].find_all('a',class_='external text')
print a_find[0]['href']
innter_url='https:'+a_find[0]['href']
# 调用第二个方法,目的在于通过第二级链接在此寻找我们要的经纬度数据
point= get_innter_data(innter_url)#将数据返回为一个point
return point
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
第二个方法:找到经纬度
def get_innter_data(url):
resp=urlopen(url)
html_data=resp.read().decode('utf-8')
# print (html_data)
soup=bs(html_data,'html.parser')#将读取到的网页代码用指定解析器html.parser进行解析
geo=soup.find_all('span',class_='geo')#通过soup对解析后的网页进行特定标签的读取,读取所有tr
lat=geo[0].find_all('span',class_='latitude')
print lat[0].string
lng=geo[0].find_all('span',class_='longitude')
print lng[0].string
lat_=lat[0].string
lng_=lng[0].string
point=[lat_,lng_]
return point
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
注:
这里有个小技巧对于处理找到网页源代码中,我们所需要的信息数据所在的位置,和所在的标签种类以及id等信息,可以采用鼠标右键的检查,找到源代码
第六步
已经实现三层的网站数据链接爬取后,将所有城市的url循环遍历就好了
for i in range(350,len(citys_url_data)):
print i
if i == 71:
continue
url='https://en.wikipedia.org'+citys_url_data[i]['href']
point =get_url_data(url)
if point==None:
continue
citys_url_data[i]['lat']=point[0]
citys_url_data[i]['lng']=point[1]
1
2
3
4
5
6
7
8
9
10
11
12
13
然后就可以看到数据全部存在citys_url_data的json列表里面,最后如果有需要将这个citys_url_data写入到json文件中。
import json
json.dump(citys_url_data, open('city_url.json', 'w'))
1
2
3
大功告成!
领取专属 10元无门槛券
私享最新 技术干货