Python爬蟲 --- 2.4 Scrapy之天氣預報爬蟲實踐

原文連接:https://www.fkomm.cn/article/...css

目的

寫一個真正意義上一個爬蟲,並將他爬取到的數據分別保存到txt、json、已經存在的mysql數據庫中。html

目標分析:

此次咱們要爬的是 中國天氣網:http://www.weather.com.cn/ 。隨便點開一個城市的天氣好比合肥: http://www.weather.com.cn/wea... 。咱們要爬取的就是圖中的:合肥七天的前期預報:python

![pic1]()

數據的篩選:mysql

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

![pic2]()

能夠看到咱們須要的數據,全都包裹在程序員

<ul class="t clearfix">sql

裏。 咱們用bs四、xpath、css之類的選擇器定位到這裏,再篩選數據就行。 本着學習新知識的原則,文中的代碼將會使用xpath定位。 這裏咱們能夠這樣:chrome

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

Scrapy 框架的實施:

建立scrapy項目和爬蟲:

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

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

├── 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

編寫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()

編寫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

編寫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

編寫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,
     }

讓項目跑起來:

$ scrapy crawl HFtianqi

結果展現:

文本格式:
![pic3]()

json格式:
![pic4]()

數據庫格式:
![pic5]()

此次的例子就到這裏了,主要介紹如何經過自定義PIPELINE來將爬取的數據以不一樣的方式保存。


相關文章和視頻推薦

圓方圓學院聚集 Python + AI 名師,打造精品的 Python + AI 技術課程。 在各大平臺都長期有優質免費公開課,歡迎報名收看。
公開課地址:https://ke.qq.com/course/362788                       

相關文章
相關標籤/搜索