從零開始寫Python爬蟲 --- 2.3 爬蟲實踐:天氣預報&數據存儲
上次我們只是了解了scrapy框架的基本運作方式,這次我們來寫一個真正意義上一個爬蟲,並將他爬取到的數據分別保存到txt、json、已經mysql資料庫中。
目標分析:
這次我們要爬的是 中國天氣網:http://www.tianqi.com/
隨便點開一個城市的天氣比如蘇州: http://suzhou.tianqi.com/我們要爬取的就是圖中的:江蘇蘇州天氣預報一周:數據的篩選:
我們使用chrome開發者工具,模擬滑鼠定位到相對應位置:
可以看到我們需要的數據,全都包裹在<div class="tqshow1">
里
我們用bs4、xpath、css之類的選擇器定位到這裡,再篩選數據就行。本著學習新知識的原則,文中的代碼將會使用xpath定位。這裡我們可以這樣:response.xpath(//div[@class="tqshow1"])
Scrapy 框架的實施:
創建scrapy項目和爬蟲:
scrapy startproject weathercd weatherscrapy genspider SZtianqi suzhou.tianqi.com
這樣我們就已經將準備工作做完了。
看一下當前的目錄:.├── scrapy.cfg└── weather ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── items.cpython-36.pyc │ ├── pipelines.cpython-36.pyc │ └── settings.cpython-36.pyc ├── data #我自己添加保存數據的文件夾,你們還沒有,不用在意 │ └── weather.json ├── items.py ├── middlewares.py ├── pipelines.py ├── settings.py └── spiders ├── SZtianqi.py ├── __init__.py └── __pycache__ ├── SZtianqi.cpython-36.pyc └── __init__.cpython-36.pyc
編寫items.py:
這次我們來先編寫items,十分的簡單,只需要將希望獲取的欄位名填寫進去:
import scrapyclass WeatherItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() date = scrapy.Field() week = scrapy.Field() img = scrapy.Field() temperature = scrapy.Field() weather = scrapy.Field() wind = scrapy.Field()
編寫Spider:
和上文介紹的一樣,這個部分使我們整個爬蟲的核心,
主要目的是:將Downloader發給我們的Response里篩選數據,並返回給PIPELINE處理代碼里有詳細的注釋,仔細看一下都是能看明白的,
主要是裡面會用到一些對字元串處理的小技巧。# -*- coding: utf-8 -*-import scrapy# 別忘了,將item導入進來,這樣數據才能在各個模塊之間流轉from weather.items import WeatherItemclass SztianqiSpider(scrapy.Spider): name = "SZtianqi" # 我們修改一下host,使得Scrapy可以爬取除了蘇州之外的天氣 allowed_domains = ["tianqi.com"] # 建立需要爬取信息的url列表 start_urls = [] # 需要爬的城市名稱 可以自行添加 citys = [nanjing, suzhou, shanghai] # 用一個很簡答的循環來生成需要爬的鏈接: for city in citys: start_urls.append(http:// + city + .tianqi.com) def parse(self, response): 篩選信息的函數: date = 今日日期 week = 星期幾 img = 表示天氣的圖標 temperature = 當天的溫度 weather = 當天的天氣 wind = 當天的風向 # 先建立一個列表,用來保存每天的信息 items = [] # 找到包裹著每天天氣信息的div sixday = response.xpath(//div[@class="tqshow1"]) # 循環篩選出每天的信息: for day in sixday: # 先申請一個weatheritem 的類型來保存結果 item = WeatherItem() # 觀察網頁,知道h3標籤下的不單單是一行str,我們用trick的方式將它連接起來 date = for datetitle in day.xpath(./h3//text()).extract(): date += datetitle item[date] = date item[week] = day.xpath(./p//text()).extract()[0] item[img] = day.xpath( ./ul/li[@class="tqpng"]/img/@src).extract()[0] tq = day.xpath(./ul/li[2]//text()).extract() # 我們用第二種取巧的方式,將tq里找到的str連接 item[temperature] = .join(tq) item[weather] = day.xpath(./ul/li[3]/text()).extract()[0] item[wind] = day.xpath(./ul/li[4]/text()).extract()[0] items.append(item) return items
編寫PIPELINE:
我們知道,pipelines.py是用來處理收尾爬蟲抓到的數據的,
一般情況下,我們會將數據存到本地:- 文本形式: 最基本的方式
- json格式 :方便其他程序員調用
- 資料庫: 數據量多時
我們來一一講解:
TXT(文本)格式:
import osimport requestsimport jsonimport codecsimport pymysqlclass WeatherPipeline(object): def process_item(self, item, spider): 處理每一個從SZtianqi傳過來的 item # 獲取當前工作目錄 base_dir = os.getcwd() # 文件存在data目錄下的weather.txt文件內 fiename = base_dir + /data/weather.txt # 從內存以追加的方式打開文件,並寫入對應的數據 with open(fiename, a) as f: f.write(item[date] +
) f.write(item[week] +
) f.write(item[temperature] +
) f.write(item[weather] +
) f.write(item[wind] +
) # 下載圖片 with open(base_dir + /data/ + item[date] + .png, wb) as f: f.write(requests.get(item[img]).content) return item
json格式數據:
我們想要輸出json格式的數據,最方便的是在PIPELINE里自定義一個class:
class W2json(object): def process_item(self, item, spider): 講爬取的信息保存到json 方便其他程序員調用 base_dir = os.getcwd() filename = base_dir + /data/weather.json # 打開json文件,向裡面以dumps的方式吸入數據 # 注意需要有一個參數ensure_ascii=False ,不然數據會直接為utf編碼的方式存入比如:「/xe15」 with codecs.open(filename, a) as f: line = json.dumps(dict(item), ensure_ascii=False) +
f.write(line) return item
資料庫格式(mysql):
Python對市面上各種各樣的資料庫的操作都有良好的支持,
但是現在一般比較常用的免費資料庫是mysql,我們就以這個為例。
詳細有很多同學和我一樣對資料庫一臉懵逼,但是實際上並沒有那麼難,只要掌握了基本語法,其實他就是一個高級的「文本文件」。
想要學習相關知識:http://www.runoob.com/mysql/mysql-tutorial.html- 在本地安裝mysql:
linux和mac都有很強大的包管理軟體,如apt,brew等等
window 可以直接去官網下載安裝包。brew install mysql
這裡的root並不是系統層面上的超級用戶,是mysql資料庫的超級用戶。
安裝完成後mysql服務是默認啟動的,如果重啟了電腦,需要這樣啟動(mac):mysql.server start
- 登錄mysql並創建scrapy用的資料庫:
# 登錄進mysqlmysql -uroot -p(括弧不用寫,裡面填寫自己的passwd)# 創建資料庫:scrapyDB ,以utf8位編碼格式,每條語句以』;『結尾CREATE DATABASE scrapyDB CHARACTER SET utf8;# 選中剛才創建的表:use scrapyDB;# 創建我們需要的欄位:欄位要和我們代碼里一一對應,方便我們一會寫sql語句CREATE TABLE weather(id INT AUTO_INCREMENT,date char(24),week char(24),img char(128),temperature char(24),weather char(24),wind char(24),PRIMARY KEY(id) )ENGINE=InnoDB DEFAULT CHARSET=utf8
來看一下weather表長啥樣:
show columns from weather或者:desc weather
- 安裝Python的mysql模塊:
Python下有很多操作mysql的模塊,這裡我推薦pymysql
官方文檔:Welcome to PyMySQL』s documentation!pip install pymysql
最後我們編輯與一下代碼:
class W2mysql(object): def process_item(self, item, spider): 將爬取的信息保存到mysql # 將item里的數據拿出來 date = item[date] week = item[week] temperature = item[temperature] weather = item[weather] wind = item[wind] img = item[img] # 和本地的scrapyDB資料庫建立連接 connection = pymysql.connect( host=localhost, # 連接的是本地資料庫 user=root, # 自己的mysql用戶名 passwd=********, # 自己的密碼 db=scrapyDB, # 資料庫的名字 charset=utf8mb4, # 默認的編碼方式: cursorclass=pymysql.cursors.DictCursor) try: with connection.cursor() as cursor: # 創建更新值的sql語句 sql = """INSERT INTO WEATHER(date,week,temperature,weather,wind,img) VALUES (%s, %s,%s,%s,%s,%s)""" # 執行sql語句 # excute 的第二個參數可以將sql預設語句補全,一般以元組的格式 cursor.execute( sql, (date, week, temperature, weather, wind, img)) # 提交本次插入的記錄 connection.commit() finally: # 關閉連接 connection.close() return item
編寫Settings.py
我們需要在Settings.py將我們寫好的PIPELINE添加進去,
scrapy才能夠跑起來這裡只需要增加一個dict格式的ITEM_PIPELINES,數字value可以自定義,數字越小的優先處理BOT_NAME = weatherSPIDER_MODULES = [weather.spiders]NEWSPIDER_MODULE = weather.spidersITEM_PIPELINES = {weather.pipelines.W2mysql: 300, weather.pipelines.WeatherPipeline: 500, weather.pipelines.W2json: 400}ROBOTSTXT_OBEY = True
讓項目跑起來:
scrapy crawl Sutianqi
結果展示:
文本格式:
json格式:
資料庫格式:
好了 這次的例子就到這裡了,主要介紹了如何通過自定義PIPELINE來將爬取的數據以不同的方式保存。還是那句話,代碼要自己一點一點慢慢敲,一點一點慢慢debug才能有進步
加油~ 完整的代碼也被上傳到Github了。每天的學習記錄都會 同步更新到:
微信公眾號: findyourownway知乎專欄:從零開始寫Python爬蟲 - 知乎專欄blog : www.ehcoblog.mlGithub: Ehco1996/Python-crawler
推薦閱讀:
※如何用scrapy爬取搜房網上小區的坐標值?
※【記錄】Scrapy模擬登錄cookie失效問題
※[轉載]學習Scrapy入門
※Scrapy爬蟲框架教程(三)-- 調試(Debugging)Spiders
※Python安裝Scrapy出現以下錯誤怎麼辦?