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=小學、中學或者大學®ion=地市名字&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上的內容。