1. 程式人生 > >python爬蟲十一:scrapy框架爬取天氣,存入資料庫

python爬蟲十一:scrapy框架爬取天氣,存入資料庫

小白學習:

轉:https://zhuanlan.zhihu.com/p/26885412

1.cmd下

scrapy startproject 專案名

2.我一般都是在pycharm中編寫程式碼,所以我會在idea中引入專案,這裡不知道如何在pycharm中下載scrapy模組的童鞋,可看我前面的部落格:

進入檔案下

scrapy genspider 檔名 爬取的網站
scrapy genspider SZtianqi suzhou.tianqi.com
會在資料夾下生成一個SZtianqi的檔案


3.編寫items.py這個檔案,是我們想要封裝的名字,在這裡面定義

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html

import scrapy

#我們將我們需要的名字加進去
class 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();#風速


4.編寫SZtianqi.py:作用的從網站上抓取資料,這裡和之前的get_html的方法一致,將網頁的資料篩取存入item中

# -*- coding: utf-8 -*-
import scrapy
from weather.items import WeatherItem


class 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

這裡面的

from weather.items import WeatherItem

是引入items.py的一個類,用與封裝的

5.處理封裝好的item物件,編寫pipelins.py:作用的將資料存入本地或資料庫

# -*- coding: utf-8 -*-
import os
import requests
import json
import codecs
import pymysql
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html

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

文字形式: 最基本的方式
json格式 :方便其他程式設計師呼叫
資料庫: 資料量多時

'''

#寫入txt檔案
class WeatherPipeline(object):

    def process_item(self, item, spider):
        '''
              處理每一個從SZtianqi傳過來的
              item
        '''
        #獲取當前的工作目錄
        basc_dir=os.getcwd();

        #把檔案儲存到data目錄下
        filename=basc_dir+'\\weather\\data\\weather.txt'


        #已追加的方式開啟檔案並寫入對應的資訊
        with open(filename,'a',encoding='utf-8') as f:
            f.write(item['date']+'\n')
            f.write(item['week']+'\n')
            f.write(item['temperature']+'\n')
            f.write(item['wind']+'\n')
            f.write(item['weather']+'\n')
            f.write(item['img']+'\n')

        #下載圖片
        file_img=basc_dir+'\\weather\\data\\image\\'+item['date']+'.png'
        with open(file_img,'wb') as f:
            f.write(requests.get(item['img']).content)
        #print('aaaaaaaaaaaaaaaaaaaaaaaaa')
        return item


#寫入json檔案
class W2json(object):
    def process_item(self, item, spider):
        #獲取本地檔案
        basc_dir=os.getcwd();

        json_dir=basc_dir+'\\weather\\data\\weather.json'

        # 開啟json檔案,向裡面以dumps的方式吸入資料
        # 注意需要有一個引數ensure_ascii=False ,不然資料會直接為utf編碼的方式存入比如:“/xe15”
        with codecs.open(json_dir,'a',encoding='utf-8') as f:
            line=json.dumps(dict(item),ensure_ascii=False)+'\n'
            f.write(line)

        return item


#將資料存入資料庫
class Rmysql(object):
    def process_item(self, item, spider):

        #抓取資料存入mysql

        #將資料從item中拿出來
        date=item['date'];
        week=item['week'];
        img=item['img']
        temperature=item['temperature']
        weather=item['weather']
        wind=item['wind']

        #和本地的資料庫連線起來
        connection=pymysql.connect(
            host='localhost',  # 連線的是本地資料庫
            user='root',        # 自己的mysql使用者名稱
            passwd='123456',  # 自己的密碼
            db='scrapyDB',      # 資料庫的名字
            charset='utf8mb4',     # 預設的編碼方式:
            cursorclass=pymysql.cursors.DictCursor)

        #插庫
        try:
            with connection.cursor() as cursor:
                #建立更新資料庫的sql
                sql="""INSERT INTO WEATHER(date,week,img,temperature,weather,wind) 
                    VALUES (%s, %s,%s,%s,%s,%s)"""

                #執行sql
                cursor.execute(sql,(date,week,img,temperature,weather,wind))
            #提交插入資料
            connection.commit()
        finally:
            #關閉資源   的第二個引數可以將sql預設語句補全,一般以元組的格式
            connection.close()
        return item

6.在settings中,呼叫pipelines的方法


7.執行專案

scrapy crawl SZtianqi

在編寫程式碼是可一邊測試一邊編寫從終端看結果


資料庫結果