Python爬蟲之Scrapy天氣預報實戰


目的

寫一個真正意義上一個爬蟲,並將他爬取到的數據分別保存到txt、json、已經存在的mysql數據庫中。
PS注意:很多人學Python過程中會遇到各種煩惱問題,沒有人解答容易放棄。為此小編建了個Python全棧免費答疑.裙 :七衣衣九七七巴而五(數字的諧音)轉換下可以找到了,不懂的問題有老司機解決里面還有最新Python實戰教程免非下,,一起相互監督共同進步!

目標分析:

這次我們要爬的是 中國天氣網:http://www.weather.com.cn/
隨便點開一個城市的天氣比如合肥: http://www.weather.com.cn/weather/101220101.shtml
我們要爬取的就是圖中的:合肥七天的前期預報:

 

數據的篩選:

我們使用chrome開發者工具,模擬鼠標定位到相對應位置:

 

可以看到我們需要的數據,全都包裹在

<ul class="t clearfix"> 


我們用bs4、xpath、css之類的選擇器定位到這里,再篩選數據就行。
本着學習新知識的原則,文中的代碼將會使用xpath定位。
這里我們可以這樣:

response.xpath('//ul[@class="t clearfix"]') 

Scrapy 框架的實施:

  1. 創建scrapy項目和爬蟲:

    $ scrapy startproject weather
    $ cd weather
    $ scrapy genspider HFtianqi www.weather.com.cn/weather/101220101.shtml
    

    這樣我們就已經將准備工作做完了。
    看一下當前的目錄:

    .
    ├── scrapy.cfg
    └── weather
        ├── __init__.py
        ├── __pycache__
        │   ├── __init__.cpython-36.pyc
        │   └── settings.cpython-36.pyc
        ├── items.py
        ├── middlewares.py
        ├── pipelines.py
        ├── settings.py
        └── spiders
            ├── HFtianqi.py
            ├── __init__.py
            └── __pycache__
                └── __init__.cpython-36.pyc
    
    4 directories, 11 files
    
  2. 編寫items.py:

    這次我們來先編寫items,十分的簡單,只需要將希望獲取的字段名填寫進去:

    import scrapy class WeatherItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() date = scrapy.Field() temperature = scrapy.Field() weather = scrapy.Field() wind = scrapy.Field() 
  3. 編寫Spider:

    這個部分使我們整個爬蟲的核心!!

    主要目的是:

    將Downloader發給我們的Response里篩選數據,並返回給PIPELINE處理

    下面我們來看一下代碼:

    # -*- coding: utf-8 -*- import scrapy from weather.items import WeatherItem class HftianqiSpider(scrapy.Spider): name = 'HFtianqi' allowed_domains = ['www.weather.com.cn/weather/101220101.shtml'] start_urls = ['http://www.weather.com.cn/weather/101220101.shtml'] def parse(self, response): ''' 篩選信息的函數: date = 日期 temperature = 當天的溫度 weather = 當天的天氣 wind = 當天的風向 ''' # 先建立一個列表,用來保存每天的信息 items = [] # 找到包裹着天氣信息的div day = response.xpath('//ul[@class="t clearfix"]') # 循環篩選出每天的信息: for i in list(range(7)): # 先申請一個weatheritem 的類型來保存結果 item = WeatherItem() # 觀察網頁,並找到需要的數據 item['date'] = day.xpath('./li['+ str(i+1) + ']/h1//text()').extract()[0] item['temperature'] = day.xpath('./li['+ str(i+1) + ']/p[@class="tem"]/i/text()').extract()[0] item['weather'] = day.xpath('./li['+ str(i+1) + ']/p[@class="wea"]/text()').extract()[0] item['wind'] = day.xpath('./li['+ str(i+1) + ']/p[@class="win"]/em/span/@title').extract()[0] + day.xpath('./li['+ str(i+1) + ']/p[@class="win"]/i/text()').extract()[0] items.append(item) return items 
  4. 編寫PIPELINE:

    我們知道,pipelines.py是用來處理收尾爬蟲抓到的數據的,
    一般情況下,我們會將數據存到本地:

    • 文本形式: 最基本的存儲方式
    • json格式 :方便調用
    • 數據庫: 數據量比較大時選擇的存儲方式

    TXT(文本)格式:

    import os import requests import json import codecs import pymysql class WeatherPipeline(object): def process_item(self, item, spider): print(item) # print(item) # 獲取當前工作目錄 base_dir = os.getcwd() # 文件存在data目錄下的weather.txt文件內,data目錄和txt文件需要自己事先建立好 filename = base_dir + '/data/weather.txt' # 從內存以追加的方式打開文件,並寫入對應的數據 with open(filename, 'a') as f: f.write(item['date'] + '\n') f.write(item['temperature'] + '\n') f.write(item['weather'] + '\n') f.write(item['wind'] + '\n\n') 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) + '\n' f.write(line) return item 

    數據庫格式(mysql):

    Python對市面上各種各樣的數據庫的操作都有良好的支持,
    但是現在一般比較常用的免費數據庫mysql。

    • 在本地安裝mysql:

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

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

      由於我是Mac,所以我是說Mac的安裝方式了。

      $ brew install mysql
      

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

      這里的root並不是系統層面上的超級用戶,是mysql數據庫的超級用戶。
      安裝完成后mysql服務是默認啟動的,
      如果重啟了電腦,需要這樣啟動(mac):

      $ mysql.server start
      
    • 登錄mysql並創建scrapy用的數據庫:

      # 登錄進mysql
      $ mysql -uroot -p
      
      # 創建數據庫:ScrapyDB ,以utf8位編碼格式,每條語句以’;‘結尾
      CREATE DATABASE ScrapyDB CHARACTER SET 'utf8';
      
      # 選中剛才創建的表:
      use ScrapyDB;
      
      # 創建我們需要的字段:字段要和我們代碼里一一對應,方便我們一會寫sql語句
      CREATE TABLE weather(
      id INT AUTO_INCREMENT,
      date char(24),
      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模塊:

      pip install pymysql
      

      最后我們編輯與一下代碼:

      class W2mysql(object): def process_item(self, item, spider): ''' 將爬取的信息保存到mysql ''' # 將item里的數據拿出來 date = item['date'] temperature = item['temperature'] weather = item['weather'] wind = item['wind'] # 和本地的scrapyDB數據庫建立連接 connection = pymysql.connect( host='127.0.0.1', # 連接的是本地數據庫 user='root', # 自己的mysql用戶名 passwd='********', # 自己的密碼 db='ScrapyDB', # 數據庫的名字 charset='utf8mb4', # 默認的編碼方式: cursorclass=pymysql.cursors.DictCursor) try: with connection.cursor() as cursor: # 創建更新值的sql語句 sql = """INSERT INTO WEATHER(date,temperature,weather,wind) VALUES (%s, %s, %s, %s)""" # 執行sql語句 # excute 的第二個參數可以將sql缺省語句補全,一般以元組的格式 cursor.execute( sql, (date, temperature, weather, wind)) # 提交本次插入的記錄 connection.commit() finally: # 關閉連接 connection.close() return item 
  5. 編寫Settings.py

    我們需要在Settings.py將我們寫好的PIPELINE添加進去,
    scrapy才能夠跑起來

    這里只需要增加一個dict格式的ITEM_PIPELINES,
    數字value可以自定義,數字越小的優先處理

    BOT_NAME = 'weather' SPIDER_MODULES = ['weather.spiders'] NEWSPIDER_MODULE = 'weather.spiders' ROBOTSTXT_OBEY = True ITEM_PIPELINES = { 'weather.pipelines.WeatherPipeline': 300, 'weather.pipelines.W2json': 400, 'weather.pipelines.W2mysql': 300, } 
  6. 讓項目跑起來:

    $ scrapy crawl HFtianqi
    
  7. 結果展示:

    文本格式:

     

    json格式:

     

    數據庫格式:

     

這次的例子就到這里了,主要介紹如何通過自定義PIPELINE來將爬取的數據以不同的方式保存。注意:很多人學Python過程中會遇到各種煩惱問題,沒有人解答容易放棄。為此小編建了個Python全棧免費答疑.裙 :七衣衣九七七巴而五(數字的諧音)轉換下可以找到了,不懂的問題有老司機解決里面還有最新Python實戰教程免非下,,一起相互監督共同進步!

本文的文字及圖片來源於網絡加上自己的想法,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯系我們以作處理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM