scrapy爬蟲框架呼叫百度地圖api資料存入資料庫

realDanielWu發表於2021-04-30

scrapy安裝配置不在本文 提及,

1.在開始爬取之前,必須建立一個新的Scrapy專案。進入自定義的專案目錄中,執行下列命令

scrapy startproject mySpider
  • 其中, mySpider 為專案名稱,可以看到將會建立一個 mySpider 資料夾,目錄結構大致如下:
  • 下面來簡單介紹一下各個主要檔案的作用:

    scrapy.cfg :專案的配置檔案

    mySpider/ :專案的Python模組,將會從這裡引用程式碼

    mySpider/items.py :專案的目標檔案

    mySpider/pipelines.py :專案的管道檔案

    mySpider/settings.py :專案的設定檔案

    mySpider/spiders/ :儲存爬蟲程式碼目錄

     mySpider/spiders/__init__.py :爬蟲主要處理邏輯

2.  今天通過爬蟲呼叫 百度地圖api來獲取 全國學校的經緯度資訊 併入庫。

     百度地圖介面api :http://api.map.baidu.com/place/v2/search?query=小學、中學或者大學&region=地市名字&output=json&ak=你的開發者ak&page_num=頁碼

  1)開啟mySpider目錄下的items.py

              Item 定義結構化資料欄位,用來儲存爬取到的資料,也是爬取資料後匯出的欄位,有點像Python中的dict字典,但是提供了一些額外的保護減少錯誤。

    可以通過建立一個 scrapy.Item 類, 並且定義型別為 scrapy.Field的類屬性來定義一個Item。

    items.py

 1 import scrapy
 2 
 3 
 4 class GetpointItem(scrapy.Item):
 5     # define the fields for your item here like:
 6     # name = scrapy.Field()
 7     name = scrapy.Field()  #學校名稱
 8     lat = scrapy.Field()   #緯度
 9     lng = scrapy.Field()   #經度11     city = scrapy.Field()  #地市
12     area = scrapy.Field()  #區縣
13     address = scrapy.Field()  #地址
14     types = scrapy.Field()    #學校型別(小學,中學,大學)

     2) 開啟 mySpider/spiders目錄裡的 __init__.py寫邏輯 ,直接上程式碼,有註釋

 1 import scrapy
 2 import json
 3 from urllib.parse import urlencode
 4 from .. import items
 5 class DmozSpider(scrapy.Spider):
 6     name = "map"
 7     allowed_domains = []
 8     #三層迴圈陣列分別請求api,由於百度api返回的資料不是所有,所以必須傳入頁碼,來爬取更多資料。
10     def start_requests(self):
11         cities = ['北京','上海','深圳']14         types =['小學','中學','大學']
15         for city in cities:
16             for page in range(1, 16):
17                 for type_one in types:
18                     base_url = 'http://api.map.baidu.com/place/v2/search?'
19                     params = {
20                         'query': type_one,
21                         'region': city,
22                         'output':'json',
23                         'ak': '你的ak',
25                         'page_num': page
26                     }
27                     url = base_url + urlencode(params)
28                     yield scrapy.Request(url, callback=self.parse,meta={"types":type_one})
29 
30     def parse(self, response):
31         res = json.loads(response.text) #請求回來資料需轉成json
32         result= res.get('results')
33         types = response.meta["types"]  #由於api返回來資料沒有學校type的資料,這裡需要自己接一下 傳參時的type引數
34         #print(types)
35         if result:
36             for result_one in result:
37                 item = items.GetpointItem() #呼叫item的GetpointItem類,匯出item
38                 item['name'] = result_one.get('name')
39                 item['lat'] = result_one.get('location').get('lat')
40                 item['lng'] = result_one.get('location').get('lng')42                 item['city'] = result_one.get('city')
43                 item['area'] = result_one.get('area')
44                 item['types'] = types
45                 item['address'] = result_one.get('address')
46                 yield item
47         else:
48              print('網路請求錯誤')

  3)item匯出來了,資料獲取到了,然後 入庫,開啟pipelines.py ,程式碼如下:

from itemadapter import ItemAdapter
import pymysql
import json

class DBPipeline(object):
    def __init__(self):
        # 連線MySQL資料庫
        self.connect=pymysql.connect(host='localhost',user='root',password='1q2w3e',db='mapspider',port=3306)
        self.cursor=self.connect.cursor()
    def process_item(self, item, spider):
        # 往資料庫裡面寫入資料
        try:
            self.cursor.execute("""select * from school where name = %s""", item['name'])
            ret = self.cursor.fetchone()
            if ret:
                print(item['name']+'***********資料重複!***************')
            else:
                self.cursor.execute(
                """insert into school(name, lng, lat, type,city,county,address)
                value (%s, %s, %s, %s, %s, %s, %s)""",
                (
                 item['name'],
                 json.dumps(item['lng']),
                 json.dumps(item['lat']),
                 item['types'],
                 item['city'],
                 item['area'],
                 item['address']
                 ))
                self.connect.commit()
                return item
        except Exception as eror:
            print('錯誤')
    # 關閉資料庫
    def close_spider(self,spider):
        self.cursor.close()
        self.connect.close()

重複資料的話,fecthOne直接排除 ,入庫。。。。,

4)執行指令碼 scray crawl map

scrapy crawl map

name 要寫對哦

回車 ,開始 唰唰唰

 

成果如下:

    

     期間 ,百度地圖 api 多次併發,不讓訪問了,多爬幾次就好了,程式邏輯 曉得就好了。

 介面api爬完了,下次爬一爬 頁面xpath上的內容。

相關文章