Python + Postgresql + PostGIS爬蟲獲取某地圖POI數據

 

1. 作者聲明

項目純屬學習娛樂,不用於任何商業盈利模式,首先對地圖平臺道一聲對不起,未經容許,擅自爬取數據。

2. 項目介紹

2.1. 項目技術

2.1.1. python3.7安裝以及pip工具安裝

https://www.python.org/

2.1.2. urllib3網絡請求包安裝(爬蟲需要)

https://pypi.org/search/

pip install urllib3

2.1.3. postgresql數據庫安裝(如需要空間數據編輯,自行安裝postgis)

https://www.postgresql.org/download/

http://postgis.net/install/

2.1.4. 數據庫連接池包

(1)數據庫初始化配置Database,安裝包psycopg2

pip install psycopg2

https://blog.csdn.net/weixin_40547993/article/details/90756631 

(2)數據庫連接池包安裝

pip install DBUtils

2.2. 項目功能與部分源碼分析

2.2.1.  pg庫數據庫連接池配置

 (1)數據庫初始化和池化參數

# postgresql
db = {
    'dbDriver': {
        'user': 'postgres',
        'password': 'postgres',
        'host': 'localhost',
        'port': 5432,
        'dbname': 'postgres',
        'application_name': 'bmapdata'
    },

    'poolDB': {
        # 連接池允許的最大連接數,0和None表示沒有限制
        'maxconnections': 100,
        # 初始化時,連接池至少創建的空閒連接,0表示不創建
        'mincached': 2,
        # 連接池中空閒的最多連接數,0和None表示沒有限制
        'maxcached': 5,
        # 連接池中最多共享的連接數量,0和None表示全部共享
        'maxshared': 20,
        # 連接池中如果沒有可用共享連接後,是否阻塞等待,True表示等等,
        # False表示不等待然後報錯
        'blocking': True
    }

}

 (2)數據庫連接池和初始化配置

import psycopg2
import importlib
import logger
import sys
from DBUtils.PooledDB import PooledDB
from DBUtils.PersistentDB import PersistentDB, PersistentDBError, NotSupportedError

sys.path.append(sys.path[0] + '/../')

# db class


class DataBase:
    # init
    def __init__(self, match):
        try:
            dbParms = importlib.import_module('config.dataSource').db
            self.poolDB = PooledDB(
                # 指定數據庫連接驅動
                creator=psycopg2,
                # 連接池允許的最大連接數,0和None表示沒有限制
                maxconnections=5,
                # 初始化時,連接池至少創建的空閒連接,0表示不創建
                mincached=2,
                # 連接池中空閒的最多連接數,0和None表示沒有限制
                maxcached=5,
                # 連接池中最多共享的連接數量,0和None表示全部共享(其實沒什麼卵用)
                maxshared=3,
                # 連接池中如果沒有可用共享連接後,是否阻塞等待,True表示等等,
                # False表示不等待然後報錯
                blocking=True,
                # 開始會話前執行的命令列表
                setsession=[],
                # ping Mysql服務器檢查服務是否可用
                ping=0,
                **dbParms['dbDriver']
            )
            self.connection = self.poolDB.connection()
            self.cursor = self.connection.cursor()
            self.schema = match["schema"]
            self.tableName = match["tableName"]
        except Exception as e:
            logger.error('數據庫連接錯誤:%s' % e)
            raise

    # 取單條數據
    def query(self, sql, data):
        cur = self.cursor
        cur.execute(sql, data)
        return cur.fetchone()

    def insert(self, sql, datas):
        conn = self.connection
        try:
            cur = self.cursor
            # 執行sql語句
            cur.executemany(
                sql, datas)
            # 提交到數據庫執行
            conn.commit()
            print("數據新增成功")
        except Exception as e:
            # 如果發生錯誤則回滾
            conn.rollback()
            logger.error('數據新增失敗:%s' % e)

    def update(self, sql, datas):
        conn = self.connection
        try:
            cur = self.cursor
            # 執行sql語句
            cur.executemany(
                sql, datas)
            # 提交到數據庫執行
            conn.commit()
            print("數據更新成功")
        except Exception as e:
            # 如果發生錯誤則回滾
            conn.rollback()
            logger.error('數據更新失敗:%s' % e)

    def delete(self, sql):
        self.transact(sql)

    def transact(self, sql):
        conn = self.connection
        try:
            cur = self.cursor
            # 執行sql語句
            cur.execute(sql)
            # 提交到數據庫執行
            conn.commit()
        except:
            # 如果發生錯誤則回滾
            conn.rollback()

2.2.2. 爬蟲請求封裝

import urllib3
import json


class Urllib3Request:
    def __init__(self):
        self.http = urllib3.PoolManager()

    # get
    def urllib3Get(self, url, param):
        req = self.http.request(
            'GET',
            url,
            fields=param)

        if req.status == 200:
            data = json.loads(req.data.decode('utf-8'))
            return data
        return {}

2.2.3. 數據入庫

(1)爬蟲數據格式轉換

(2)數據庫表實體類封裝


# POI實體類


class POIEntity:
    def __init__(self, result):
        self.uid = result["uid"] if "uid" in result else None
        self.name = result["name"] if "name" in result else None
        self.address = result["address"] if "address" in result else None
        self.province = result["province"] if "province" in result else None
        self.city = result["city"] if "city" in result else None
        self.area = result["area"] if "area" in result else None
        self.street_id = result["street_id"] if "street_id" in result else None
        self.tag = result["detail_info"]["tag"] if "detail_info" in result and "tag" in result["detail_info"] else None
        self.type = result["detail_info"]["type"] if "detail_info" in result and "type" in result["detail_info"] else None
        self.detail_url = result["detail_info"]["detail_url"] if "detail_info" in result and "detail_url" in result["detail_info"] else None
        self.telephone = result["telephone"] if "telephone" in result else None
        self.lng = result["location"]["lng"] if "location" in result and "lng" in result["location"] else None
        self.lat = result["location"]["lat"] if "location" in result and "lat" in result["location"] else None

(3)數據入庫

數據新增,判斷是否已有,已有數據進行更新操作,否則新增

數據效果圖

3. 地圖展示(無奈,暫時沒有配圖配色)

QGIS簡易效果圖展示

4. 項目源碼地址

https://github.com/yangdengxian/BMapData

5. 著作權聲明

本博文屬博主原創,如需參考或者轉載,註明緣由,創作不易,多多支持與諒解,也希望廣大技術人員相互探討

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章