1. 程式人生 > >scrapy專案總結——爬取汙染資料的專案

scrapy專案總結——爬取汙染資料的專案

經過一段時間的學習,開始慢慢學會了使用scray簡單的爬取資料。 這個專案起源是對汙染資料的需求。 起初找到一個網站,嘗試對其進行爬取,但是網站涉及到動態載入的問題,目前本人只學會了靜態網站的爬取,所以放棄了。等後期學習後會返回進行嘗試。網址為:

https://www.aqistudy.cn/historydata/

本專案實際使用的資源為:

http://www.tianqihoubao.com/aqi/

首先進行專案建立;

scrapy startproject Aqi

在建立好的scrapy容器裡面建立一個spider:WRS,中間程式碼片如下:

import scrapy
from
Aqi.items import AqiItem class AQISpider(scrapy.Spider): name = 'WRS' start_urls = ['http://www.tianqihoubao.com/aqi/'] #這裡必須為start_urls,兩次專案都在這個s處尋找半天debug # allowed_domains = ['tianqihoubao.com'] def parse(self, response): for url in response.xpath('//*[@id="content"]/div/dl/dd/a/@href'
).extract()[9:]: full_url = response.urljoin(url) yield scrapy.Request(full_url, callback=self.parse_city) def parse_city(self, response): for url in response.xpath('//*[@id="bd"]/div[1]/div[3]/ul/li/a/@href').extract(): try: full_url = response.urljoin(url) finally
: yield scrapy.Request(full_url, callback=self.parse_month) def parse_month(self, response): #這裡是一個對爬取到的資料的處理(求平均值),進行過3次嘗試。還是基礎知識不太紮實 def avera(ur): av = 0 for i in ur: av = av + float(i) aver = av / len(ur) return aver item = AqiItem() item['city'] = response.xpath('//*[@id="bd"]/div[2]/div[4]/h2/text()').extract() #因為chrome瀏覽器的原因,造成網頁原始碼裡不含tbody;但是審查元素時瀏覽器會自動加上tbody,故直接刪除tvbody即可 item['AQI'] = avera(response.xpath('//*[@id="content"]/div[3]/table/tr/td[3]/text()').extract()[1:]) item['PM25'] = avera(response.xpath('//*[@id="content"]/div[3]/table/tr/td[5]/text()').extract()[1:]) item['PM10'] = avera(response.xpath('//*[@id="content"]/div[3]/table/tr/td[6]/text()').extract()[1:]) item['So2'] = avera(response.xpath('//*[@id="content"]/div[3]/table/tr/td[7]/text()').extract()[1:]) item['No2'] = avera(response.xpath('//*[@id="content"]/div[3]/table/tr/td[8]/text()').extract()[1:]) item['Co'] = avera(response.xpath('//*[@id="content"]/div[3]/table/tr/td[9]/text()').extract()[1:]) item['O3'] = avera(response.xpath('//*[@id="content"]/div[3]/table/tr/td[10]/text()').extract()[1:]) yield item #for aA in response.xpath('//*[@id="content"]/div[3]/table/tr/td[1]/text()').extract(): #AQI = #for i in range(1, (1+len(response.xpath('//*[@id="content"]/div[3]/table/tr/td[1]/text()').extract()))): #item = AqiItem() #item['city'] = response.xpath('//*[@id="content"]/div[3]/h4/text()').extract() #item['time'] = response.xpath('//*[@id="content"]/div[3]/table/tr/td[1]/text()').extract()[i] #item['AQI'] = float(response.xpath('//*[@id="content"]/div[3]/table/tr/td[3]/text()').extract()[i]) #item['PM25'] = float(response.xpath('//*[@id="content"]/div[3]/table/tr/td[5]/text()').extract()[i]) #item['PM10'] = float(response.xpath('//*[@id="content"]/div[3]/table/tr/td[6]/text()').extract()[i]) # item['So2'] = float(response.xpath('//*[@id="content"]/div[3]/table/tr/td[7]/text()').extract()[i]) # item['No2'] = float(response.xpath('//*[@id="content"]/div[3]/table/tr/td[8]/text()').extract()[i]) # item['Co'] = float(response.xpath('//*[@id="content"]/div[3]/table/tr/td[9]/text()').extract()[i]) # item['O3'] = float(response.xpath('//*[@id="content"]/div[3]/table/tr/td[10]/text()').extract()[i]) # finally: # yield item #item = AqiItem() #item['city'] = response.xpath('//*[@id="content"]/h1/text()').extract() #item['time'] = response.xpath('//*[@id="content"]/div[3]/table/tr/td[1]/text()').extract()[1:] #item['AQI'] = response.xpath('//*[@id="content"]/div[3]/table/tr/td[3]/text()').extract()[1:] #item['PM25'] = response.xpath('//*[@id="content"]/div[3]/table/tr/td[5]/text()').extract()[1:] #item['PM10'] = response.xpath('//*[@id="content"]/div[3]/table/tr/td[6]/text()').extract()[1:] #item['So2'] = response.xpath('//*[@id="content"]/div[3]/table/tr/td[7]/text()').extract()[1:] #item['No2'] = response.xpath('//*[@id="content"]/div[3]/table/tr/td[8]/text()').extract()[1:] #item['Co'] = response.xpath('//*[@id="content"]/div[3]/table/tr/td[9]/text()').extract()[1:] #item['O3'] = response.xpath('//*[@id="content"]/div[3]/table/tr/td[10]/text()').extract()[1:] #yield item

在spider裡面,主要問題就是兩個問題:

  1. start_urls
  2. 對基礎不太熟悉,導致浪費時間在處理上
  3. 目前兩個專案都存在的一個問題:每次爬取到的資料第一個列表都不需要,兩次都是使用不同的方法去除第一個列表,所以需要總結一個固定的方法丟擲第一個資料 在items.py裡面建立需要返回的item:
# -*- 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 AqiItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    city = scrapy.Field()
    # time = scrapy.Field()
    AQI = scrapy.Field()
    PM25 = scrapy.Field()
    PM10 = scrapy.Field()
    So2 = scrapy.Field()
    No2 = scrapy.Field()
    Co = scrapy.Field()
    O3 = scrapy.Field()
    pass

對應item,新建一個PipeLine對返回的資料進行操作:

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

# 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
import time


class AqiFilePipeLine(object):
    def __init__(self):
        self.file = open('d:/Aqi/wuqueshi.txt', 'wb')

    def process_item(self, item, spider):
        line = "%s,%s,%s,%s,%s,%s,%s,%s\r\n" % (item['city'],  item['AQI'], item['PM25'],
                                                item['PM10'], item['So2'], item['No2'], item['Co'], item['O3'])
        self.file.write(line.encode("utf-8"))
        #fp.write(item['city'] + '\t')
            #fp.write(item['time'] + '\t')
            #fp.write(item['AQI'] + '\t')
            #fp.write(item['PM25'] + '\t')
            #fp.write(item['PM10'] + '\t')
            #fp.write(item['So2'] + '\t')
            #fp.write(item['No2'] + '\t')
            #fp.write(item['Co'] + '\t')
            #fp.write(item['O3'] + '\n\n')
        time.sleep(0.2)
        return item

在匯出資料這裡,進行過多次嘗試,每次得到的資料格式都不太滿意。因為最初沒有算出平均值,而是直接得出所需要的日資料,而每一個原始資料都存在\r\n;所以都會有大量空格存在。處理方法為:將得到的數字資料轉化為float格式,城市資料來源改變,日期資料刪除。但是沒有解決這個問難。希望後續可以補上。 這裡若是不設定time.sleep。則得到的資料可能會相應減少,因為訪問網站的頻率過快。 對應的PipeLine,設定相應的Setting,其中的AUTOTHROTTLE_ENABLED 應該去除註釋,可以得到更完整的資料:

AUTOTHROTTLE_ENABLED = True

。本專案的缺點在於:

  1. 遇到動態載入的網站沒有找到爬取的方法
  2. start_urls問題為老問題
  3. 爬取資料的第一行仍然沒有固定的方法排除
  4. 得到的結果因為不明原因會有缺失,並且得到的資料格式與網頁資料不符