python使用scrapy爬取百度地图POI数据

该博客介绍了如何利用百度地图开放平台的接口抓取点兴趣(POI)数据,并使用Scrapy爬虫框架进行处理。数据爬取后,通过Python的psycopg2库将结果存储到PostgreSQL数据库中,实现地理信息的存储。博客还展示了关键代码,包括请求数据、解析响应、去重以及数据库操作等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前面已经介绍过使用scrapy爬取百度图片内容,这里介绍一下通过百度地图提供的接口爬取POI数据,并且保存到postgresql数据库中。图片爬虫与数据爬虫处理的方式还是有一些不一样的。

在百度地图开放平台上可以找到相关的地点检索的文档,关于接口的使用方法有很详细的描述,主要还是通过关键词和POI分类进行检测,注意不同的关键词可能得到的数据有重复,注意通过uid来去重。
接口文档
具体的创建项目的过程,前面的博文里已经讲过,这里只展示一下核心代码

请求数据代码farm.py

import scrapy
import json

from catchFarm.items import CatchfarmItem

print("构造")


class FarmSpider(scrapy.Spider):
    name = 'farm'
    allowed_domains = ['api.map.baidu.com']
    url = 'https://api.map.baidu.com/place/v2/search?query=牧业&tag=公司企业&region={}&output=json&ak=你申请的ak&coord_type=1'
    print("开始")
    # 每次请求一个市的,市列表在这
    areas = [
        {
            "name": '郑州市',
            "code": '268'
        }, {
            "name": '驻马店市',
            "code": '269'
        }, {
            "name": '安阳市',
            "code": '267'
        }, {
            "name": '新乡市',
            "code": '152'
        }, {
            "name": '洛阳市',
            "code": '153'
        }, {
            "name": '商丘市',
            "code": '154'
        }, {
            "name": '许昌市',
            "code": '155'
        }, {
            "name": '濮阳市',
            "code": '209'
        },
        {
            "name": '开封市',
            "code": '210'
        }, {
            "name": '焦作市',
            "code": '211'
        }, {
            "name": '三门峡市',
            "code": '212'
        }, {
            "name": '平顶山市',
            "code": '213'
        }, {
            "name": '信阳市',
            "code": '214'
        }, {
            "name": '鹤壁市',
            "code": '215'
        }, {
            "name": '周口市',
            "code": '308'
        },
        {
            "name": '南阳市',
            "code": '309'
        },
        {
            "name": '漯河市',
            "code": '344'
        }
    ]
    index = 0
    start_urls = [url.format(areas[0]['code'])]
    print(start_urls)

    def parse(self, response):
        print(response.text)
        print("第{}次请求".format(str(self.index)))

        results = json.loads(response.text)
        results = results["results"]
        for result in results:
            item = CatchfarmItem()
            # 异常数据处理
            if 'location' not in result.keys():
                continue
            # 解析数据    
            item['name'] = result['name']
            item['lat'] = result['location']['lat']
            item['lng'] = result['location']['lng']
            item['address'] = result['address']
            item['province'] = result['province']
            item['city'] = result['city']
            item['area'] = result['detail']
            item['uid'] = result['uid']
            yield item

        self.index = self.index + 1
        if self.index >= len(self.areas):
            return
        yield scrapy.Request(self.update_url(),
                             callback=self.parse)

    def update_url(self):
        print(self.url.format(self.areas[self.index]['code']))
        return self.url.format(self.areas[self.index]['code'])

item.py

import scrapy


class CatchfarmItem(scrapy.Item):
    # define the fields for your item here like:
    name = scrapy.Field()
    lat = scrapy.Field()
    lng = scrapy.Field()
    address = scrapy.Field()
    province = scrapy.Field()
    city = scrapy.Field()
    area = scrapy.Field()
    detail = scrapy.Field()
    uid = scrapy.Field()

    pass

pipelines.py

import psycopg2

# useful for handling different item types with a single interface
from itemadapter import ItemAdapter


class CatchfarmPipeline(object):

    def __init__(self):
        self.cursor = None
        self.conn = None
        self.conn = psycopg2.connect(database="postgres",
                                     user="postgres",
                                     password="postgres",
                                     host="127.0.0.1",
                                     port="5432")

        self.cursor = self.conn.cursor()
    def open_spider(self, spider):
        pass

    def process_item(self, item, spider):
        # id存在则不插入
        sql = "INSERT INTO postgres.farm_baidu(name, lat, lng, address, province, city, area, uid, geom) " \
              "VALUES ('{}', {}, {},'{}', '{}', '{}', '{}', '{}',st_point({},{},4326) ) on conflict(uid)  do nothing"
        sql = sql.format(item['name'], item['lat'], item['lng'], item['address'], item['province'], item['city'],
                         item['area'], item['uid'], item['lng'], item['lat'])
        print(sql)
        self.cursor.execute(sql)

        return item

    def close_spider(self, spider):
        self.conn.commit()
        self.cursor.close()
        # 关闭数据库连接
        self.conn.close()

settings.py

BOT_NAME = 'catchFarm'

SPIDER_MODULES = ['catchFarm.spiders']
NEWSPIDER_MODULE = 'catchFarm.spiders'




# Obey robots.txt rules
ROBOTSTXT_OBEY = False

# Configure maximum concurrent requests performed by Scrapy (default: 16)
CONCURRENT_REQUESTS = 1


DOWNLOAD_DELAY = 3
# 设置延迟

ITEM_PIPELINES = {
   'catchFarm.pipelines.CatchfarmPipeline': 300,
}

爬取结果

爬取结果

### 使用Python实现百度地图POI数据的网络爬虫 为了使用Python编写一个能够抓取百度地图POIPoint of Interest)数据的网络爬虫,主要依赖于`requests`库发送HTTP请求以及解析返回的数据。下面是一个简单的例子展示如何完成这一目标。 #### 准备工作 首先需要注册成为百度LBS云平台开发者并创建应用以获得API Key[^1]。接着安装必要的Python包: ```bash pip install requests pandas psycopg2-binary ``` 其中`psycopg2-binary`用于连接PostgreSQL数据库存储获取的信息;而`pandas`可以帮助更好地处理结构化表格型数据。 #### 编写代码调用API 构建函数来封装向百度地图Web服务发起查询的过程。此部分涉及设置URL参数如位置范围、检索关键字等,并通过GET方法传递给服务器端口。 ```python import json from urllib.parse import urlencode, quote_plus def fetch_poi(api_key, location, radius=1000, query=""): base_url = "http://api.map.baidu.com/place/v2/search?" params = { 'query': query, 'location': str(location), 'radius': str(radius), # 半径,默认为1公里 'output': 'json', 'ak': api_key } url = f"{base_url}{urlencode(params)}" response = requests.get(url).text return json.loads(response) ``` 上述代码片段定义了一个名为`fetch_poi()` 的辅助函数,它接受多个输入参数以便灵活调整每次请求的具体条件[^2]。 #### 数据存入PostgreSQL 当成功接收到响应后,则需进一步提取有用字段并将它们整理成适合长期保存的形式——比如CSV文件或是关系型数据库表记录。这里选择了后者作为持久化的手段之一。 ```python import psycopg2 conn_info = { "host": "localhost", "database": "your_database_name", "user": "username", "password": "password" } connection = None try: connection = psycopg2.connect(**conn_info) cursor = connection.cursor() create_table_query = ''' CREATE TABLE IF NOT EXISTS pois ( id SERIAL PRIMARY KEY, name VARCHAR(255), address TEXT, latitude NUMERIC, longitude NUMERIC); ''' cursor.execute(create_table_query) except (Exception, psycopg2.DatabaseError) as error : print ("Error while connecting to PostgreSQL", error) finally: if(connection): cursor.close() connection.commit() connection.close() # 插入新条目... for item in poi_data['results']: insert_query = """ INSERT INTO pois(name,address, latitude, longitude) VALUES (%s,%s,%s,%s);""" try: connection = psycopg2.connect(**conn_info) cursor = connection.cursor() record_to_insert = (item["name"], item["address"], float(item["location"]["lat"]), float(item["location"]["lng"])) cursor.execute(insert_query,record_to_insert ) except Exception as e: print(f"Failed inserting {e}") finally: if(connection): cursor.close() connection.commit() connection.close() ``` 这段脚本展示了怎样建立与本地实例之间的通信链路,并执行SQL语句操作指定模式下的特定对象。对于每一个来自在线资源的新实体都将被追加至预先声明好的集合内。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GIS开发者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值