從零開始寫Python爬蟲 --- 2.3 爬蟲實踐:天氣預報&數據存儲

上次我們只是了解了scrapy框架的基本運作方式,這次我們來寫一個真正意義上一個爬蟲,並將他爬取到的數據分別保存到txt、json、已經mysql資料庫中。

目標分析:

這次我們要爬的是 中國天氣網: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,我們就以這個為例。

詳細有很多同學和我一樣對資料庫一臉懵逼,但是實際上並沒有那麼難,只要掌握了基本語法,其實他就是一個高級的「文本文件」。

想要學習相關知識:runoob.com/mysql/mysql-

    • 在本地安裝mysql:

linux和mac都有很強大的包管理軟體,如apt,brew等等

window 可以直接去官網下載安裝包。

brew install mysql

在安裝的過程中,他會要求你填寫root用戶的密碼,

這裡的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.ml

Github: Ehco1996/Python-crawler

推薦閱讀:

如何用scrapy爬取搜房網上小區的坐標值?
【記錄】Scrapy模擬登錄cookie失效問題
[轉載]學習Scrapy入門
Scrapy爬蟲框架教程(三)-- 調試(Debugging)Spiders
Python安裝Scrapy出現以下錯誤怎麼辦?

TAG:Python | scrapy | 爬虫 |