用 Python 从维基百科、百度百科等网站抓取公开的数据,并存储到表格中,这不是什么难事儿。但在很多利用场景中,咱们不再局限于把抓取的数据存储到表格,还须要更直观的去可视化。比方在本案例中,用 Python 从维基百科抓取往届举办冬奥会的城市,而后制作出地图、图库,甚至进行灵便的共享合作。要实现这些,如果抓取数据后再用 Python 去做网页来可视化和共享,就会比较复杂,效率也不高,对于很多非专业人员来说,更是限度了施展。而如果联合 SeaTable 表格来实现就会十分不便,谁都能够上手。它作为新型的在线协同表格和信息管理工具,不仅能不便地治理各类型数据,还提供了丰盛的数据可视化性能,也有欠缺的 Python API 性能等。
本文就来分享如何用 Python 从维基百科中抓取城市数据,而后主动填入到 SeaTable 表格中,并用 SeaTable 表格的可视化插件主动生成地图、图库等。下图是冬奥会举办城市的根底表格。
工作指标:通过每个城市的维基百科链接,去查找该城市对应的地理位置(经纬度)并填入到“经纬度“字段,同时在维基百科中把该城市的宣传图片下载一张,并上传到“城市图片“字段。
主动获取城市经纬度到表格“经纬度”字段
从网页中获取信息,须要一些简略的 python 爬虫技术。该工作中采纳 requests 和 beatifulsoup 的 Python 模块进行实现,其中 requests 模块能够模仿线上申请,返回一段 html 的 DOM 树,beatifulsoup 通过解析 DOM 树来获取标签中的想要的信息。以维基百科中的一个城市经纬度为例,该 DOM 树的构造如下:
只有在网页中能看到的信息,通过 DOM 树的源代码都能够查问到其地位所在,通过简略的解析能够提取出想要的内容。具体的解析办法能够参照 beautifulsoup 文档。
以下给了一个通过 url 解析其经纬度信息的代码:
import requests
from bs4 import BeautifulSoup
url = "https://en.wikipedia.org/wiki/Chamonix" # 维基百科的城市链接
# 申请该链接,获取其内容,网页内容是一段 DOM 树
resp = requests.get(url)
# 把获取的内容装进 beatifulsoup 解析器,以待解析
soup = BeautifulSoup(resp.content)
# 纬度,找到 DOM 属性 class 为 longitude 的构造,获取其标签值
lon = soup.find_all(attrs={"class": "longitude"})[0].string
# 经度, 找到 DOM 属性 class 为 latitude 的构造,获取其标签值
lat = soup.find_all(attrs={"class": "latitude"})[0].string
通过以上找进去的经度纬度的格局是规范的天文格局,写成如 45° 55′ 23.16″ N, 6° 52′ 10.92″ E,存入 SeaTable 表格中须要将其转换成十进制的格局进行写入。这里则须要写一个转换逻辑进行转换。
主动获取城市图片到表格“城市图片”字段
该工作中除了须要晓得经纬度的信息,还须要把一张图片下载下来,传递到表格中,同样的,图片也和经纬度一样,在 DOM 树中也能够找到其原始信息:
其中 img 标签的 src 值就是咱们须要的下载链接,联合 SeaTable API 的文件操作,能够轻松地把该图片下载下来,而后上传到表格当中。以下是该工作的残缺代码:
import requests
from bs4 import BeautifulSoup
import re
from seatable_api import Base, context
import os
import time
'''
该脚本演示了通过从维基百科举办冬奥会的城市数据中摘取相干内容,解析,并把其填入 seatable 表格中的案例
数据包含地理位置的经纬度,以及代表图片
'''SERVER_URL = context.server_url or'https://cloud.seatable.cn/'API_TOKEN = context.api_token or'cacc42497886e4d0aa8ac0531bdcccb1c93bd0f5'TABLE_NAME =" 历届举办地 "URL_COL_NAME =" 维基百科城市链接 "CITY_COL_NAME =" 举办城市 "POSITION_COL_NAME =" 经纬度 "IMAGE_COL_NAME =" 城市图片 "
def get_time_stamp():
return str(int(time.time()*10000000))
class Wiki(object):
def __init__(self, authed_base):
self.base = authed_base
self.soup = None
def _convert(self, tude):
# 把经纬度格局转换成十进制的格局,不便填入表格。multiplier = 1 if tude[-1] in ['N', 'E'] else -1
return multiplier * sum(float(x) / 60 ** n for n, x in enumerate(tude[:-1]))
def _format_position(self, corninate):
format_str_list = re.split("°|′|″", corninate)
if len(format_str_list) == 3:
format_str_list.insert(2, "00")
return format_str_list
def _get_soup(self, url):
# 初始化 DOM 解析器
resp = requests.get(url)
soup = BeautifulSoup(resp.content)
self.soup = soup
return soup
def get_tu_position(self, url):
soup = self.soup or self._get_soup(url)
# 解析网页的 DOM,取出经纬度的数值,返回十进制
lon = soup.find_all(attrs={"class": "longitude"})[0].string
lat = soup.find_all(attrs={"class": "latitude"})[0].string
converted_lon = self._convert(self._format_position(lon))
converted_lat = self._convert(self._format_position(lat))
return {
"lng": converted_lon,
"lat": converted_lat
}
def get_file_download_url(self, url):
# 解析一个 DOM,取出其中一个图片的下载链接
soup = self.soup or self._get_soup(url)
src_image_tag = soup.find_all(attrs={"class": "infobox ib-settlement vcard"})[0].find_all('img')
src = src_image_tag[0].attrs.get('src')
return "https:%s" % src
def handle(self, table_name):
base = self.base
for row in base.list_rows(table_name):
try:
url = row.get(URL_COL_NAME)
if not url:
continue
row_id = row.get("_id")
position = self.get_tu_position(url)
image_file_downlaod_url = self.get_file_download_url(url)
extension = image_file_downlaod_url.split(".")[-1]
image_name = "/tmp/wik-image-%s-%s.%s" % (row_id, get_time_stamp(), extension)
resp_img = requests.get(image_file_downlaod_url)
with open(image_name, 'wb') as f:
f.write(resp_img.content)
info_dict = base.upload_local_file(
image_name,
name=None,
relative_path=None,
file_type='image',
replace=True
)
row_data = {
POSITION_COL_NAME: position,
IMAGE_COL_NAME: [info_dict.get('url'), ]
}
base.update_row(table_name, row_id, row_data)
os.remove(image_name)
self.soup = None
except Exception as e:
print("error", row.get(CITY_COL_NAME), e)
def run():
base = Base(API_TOKEN, SERVER_URL)
base.auth()
wo = Wiki(base)
wo.handle(TABLE_NAME)
if __name__ == '__main__':
run()
以下是通过运行脚本自动化写入数据的表格后果,能够看出,比起上网查问而后手动填写每一行数据,脚本的自动化操作则能够节俭大量工夫,并且精确和高效。
用 SeaTable 的地图插件主动生成城市地图
有了后面获取的城市经纬度信息,咱们就能够从 SeaTable 表格的“插件”栏中一键增加地图插件,而后仅需简略点选,就能够依据“经纬度”字段把城市主动标记到地图上了。并且还能够标记不同的标签色彩、设置间接和悬浮显示字段等。相比于在表格中去枯燥的查看各个城市,通过地图可视化显然更加形象和直观了。
用 SeaTable 的图库插件可视化城市图片
图库插件同样能够搁置到表格工具栏,不便随时关上查看。在图库插件的设置里,同样仅需简略点选,就能够依据表格中的“城市图片”字段,把图片以图库模式展现进去,并且还能够设置题目名称、其余显示字段。这要比在表格中去浏览小图,显得更加好看也更不便了,大大晋升了浏览体验。而且点击图片还能够放大查看。点击题目还能够间接进入查看和编辑其在表格中的行内容。
另外,表格还反对灵便的共享合作权限管控,能满足粗疏的多样化的共享场景。比方想间接共享地图、图库给他人去查看,还能够间接去表格插件的内部利用里增加“地图”、“图库”。更多应用,大家能够自行去体验,这里不多做介绍。
总结
作为新型的协同表格和信息管理工具,SeaTable 不仅功能丰富,而且简略易用。平时咱们用 Python 实现一些程序时,就能够灵便联合 SeaTable 表格的性能,从而省去编程、开发、保护等工夫和人力老本,疾速又不便地实现更多乏味的事儿、更欠缺的利用。也让工具的使用施展出更大的价值。