資料採集與融合實踐作業三

早八打酱油發表於2024-10-30

資料採集與融合技術實踐作業三

scrapy專案gitee連結:https://gitee.com/jsjdjjdjajsd/getinformation/tree/master/作業三

作業①:

要求:指定一個網站,爬取這個網站中的所有的所有圖片,例如:中國氣象網(http://www.weather.com.cn)。使用scrapy框架分別實現單執行緒和多執行緒的方式爬取。
–務必控制總頁數(學號尾數2位)、總下載的圖片數量(尾數後3位)等限制爬取的措施。

輸出資訊: 將下載的Url資訊在控制檯輸出,並將下載的圖片儲存在images子檔案中,並給出截圖。
Gitee資料夾連結
建立完工程後,編寫weather_spider.py

點選檢視程式碼
import scrapy
from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem

class WeatherSpider(scrapy.Spider):
    name = 'weather_spider'
    page_limit = 19
    image_limit = 119
    start_urls = [f'http://www.weather.com.cn/']

    def parse(self, response):
        images = response.css('img::attr(src)').getall()
        for img in images:
            if img.startswith('//'):
                img = 'http:' + img
            yield {'image_urls': [img]}

        if self.page_limit > 0:
            next_page = response.css('a.next::attr(href)').get()
            if next_page is not None:
                yield response.follow(next_page, self.parse)

    def close(self, reason):
        self.log(f'Scrapy finished with reason: {reason}')

其中
page_limit = 19 image_limit = 119 start_urls = [f'http://www.weather.com.cn/']表示爬取最大頁數只能到19頁,最大圖片數只能為119.
編寫piplines.py檔案

點選檢視程式碼
from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem 

class CustomImagesPipeline(ImagesPipeline):

    def __init__(self, *args, **kwargs):
        super(CustomImagesPipeline, self).__init__(*args, **kwargs)
        self.images_count = 0

    def item_completed(self, results, item, info):
       
        self.images_count += len(results[0][1])
        if self.images_count > 119:  
            raise DropItem(f'Too many images downloaded: {self.images_count}')
        return item

接下來配置setting.py檔案

此時執行在終端執行爬蟲是單執行緒模式
加上這段程式碼CONCURRENT_REQUESTS = 16後面的數字可填任意數字,用於控制併發請求的數量,當大於1時既是多執行緒。
執行的最終結果

心得體會

透過本次實驗,我深入瞭解了Scrapy框架的強大功能及其靈活性。首先,Scrapy提供了強大的資料提取和儲存機制,使得爬取資料變得相對簡單。其次,使用單執行緒和多執行緒的比較,讓我意識到併發請求在提升爬取效率方面的顯著效果。然而,控制總頁數和圖片數量的設定讓我明白了爬蟲設計中的重要性,以避免對目標網站造成過大壓力。此外,除錯和錯誤處理的過程增強了我對Python程式設計的理解。總的來說,本次實驗不僅提升了我的程式設計能力,也讓我對網路爬蟲的實用性有了更深刻的認識。

作業②

要求:熟練掌握 scrapy 中 Item、Pipeline 資料的序列化輸出方法;使用scrapy框架+Xpath+MySQL資料庫儲存技術路線爬取股票相關資訊。
候選網站:東方財富網:https://www.eastmoney.com/
建立完工程後編寫stock_spider.py程式碼

點選檢視程式碼
import re
import scrapy
import requests
from..items import SecondbloodPipeline


class SecondSpider(scrapy.Spider):
    name = "second"
   
    start_url = "http://quote.eastmoney.com/center/gridlist.html#hs_a_board"

    def start_requests(self):
        url = SecondSpider.start_url
        yield scrapy.Request(url=url, callback=self.parse)

    def parse(self, response, **kwargs):
        try:
            stocks = []
            url = "https://68.push2.eastmoney.com/api/qt/clist/get?cb=jQuery1124009413428787683675_1696660278138&pn=1&pz=20&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&wbp2u=|0|0|0|web&fid=f3&fs=m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048&fields=f12,f14,f2,f3,f4,f5,f6,f7,f15,f16,f17,f18&_=1696660278155"
            r = requests.get(url=url)
            data = re.compile("\"f2\":.*").findall(r.text)
            data1 = data[0].split("},{")
            data1[-1] = data1[-1].split("}")[0]
            for i in range(len(data1)):
                stock0 = data1[i].replace('"', "").split(",")
                list_ = [6, 7, 0, 1, 2, 3, 4, 5, 8, 9, 10, 11]
                stock = []
                for j in list_:
                    stock.append(stock0[j].split(":")[1])
                stocks.append(stock)

            for i in range(len(stocks)):
                item = SecondbloodPipeline()
                item["stockname"] = stocks[i][0]
                item["name"] = stocks[i][1]
                item["newprice"] = float(stocks[i][2])
                item["zhangdiefu"] = float(stocks[i][3])
                item["zhangdieer"] = float(stocks[i][4])
                item["chengjiaoliang"] = float(stocks[i][5])
                item["chengjiaoer"] = float(stocks[i][6])
                item["zhenfu"] = float(stocks[i][7])
                item["zuigao"] = float(stocks[i][8])
                item["zuidi"] = float(stocks[i][9])
                item["jinkai"] = float(stocks[i][10])
                item["zuoshou"] = float(stocks[i][11])
                yield item
        except Exception as err:
            print(f"Error in parse method: {err}")

配置piplines.py檔案

點選檢視程式碼
import pymysql


class SecondbloodPipeline:
    def __init__(self):
        self.mydb = pymysql.connect(
            host="127.0.0.1",
            port=3306,
            user='root',
            password='Wjh040619@',
            database="stock",
            charset='utf8'
        )
        self.cursor = self.mydb.cursor()
        self.cursor.execute('''CREATE TABLE IF NOT EXISTS stocks(
                                      stockname VARCHAR(256),
                                      name VARCHAR(256),
                                      newprice DECIMAL(10, 2),
                                      zhangdiefu DECIMAL(5, 2),
                                      zhangdieer DECIMAL(5, 2),
                                      chengjiaoliang DECIMAL(10, 2),  
                                      chengjiaoer DECIMAL(10, 2),
                                      zhenfu DECIMAL(5, 2),
                                      zuigao DECIMAL(10, 2),
                                      zuidi DECIMAL(10, 2),
                                      jinkai DECIMAL(10, 2),
                                      zuoshou DECIMAL(10, 2)  
                                   )''')
        self.mydb.commit()

    def process_item(self, item, spider):
        try:
            sql = "INSERT INTO stocks VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
            self.cursor.execute(sql, (
                item.get("stockname"), item.get("name"), item.get("newprice"),
                item.get("zhangdiefu"), item.get("zhangdieer"),
                item.get("chengjiaoliang"), item.get("chengjiaoer"),
                item.get("zhenfu"), item.get("zuigao"),
                item.get("zuidi"), item.get("jinkai"),
                item.get("zuoshou")))
            self.mydb.commit()
            print("Successfully inserted:", item)
        except Exception as e:
            print(f"Error inserting item: {e}")
            self.mydb.rollback()
        return item

    def close_spider(self, spider):
        self.cursor.close()
        self.mydb.close()

其中self.mydb = pymysql.connect( host="127.0.0.1", port=3306, user='root', password='Wjh040619@', database="stock", charset='utf8' )用於連線自己本地的mysql資料庫

配置items.py檔案

點選檢視程式碼
import scrapy


class SecondbloodPipeline(scrapy.Item):
    stockname = scrapy.Field()
    name = scrapy.Field()
    newprice = scrapy.Field()
    zhangdiefu = scrapy.Field()
    zhangdieer = scrapy.Field()
    chengjiaoliang = scrapy.Field()
    chengjiaoer = scrapy.Field()
    zhenfu = scrapy.Field()
    zuigao = scrapy.Field()
    zuidi = scrapy.Field()
    jinkai = scrapy.Field()
    zuoshou = scrapy.Field()

確保資料庫裡的資料儲存格式
新增settings.py的一條內容

確保piplines.py能夠正常啟用
在終端開啟mysql建立名為stock的資料庫後執行爬蟲程式碼,即可得到輸出的結果

心得體會

透過本次作業,我對Scrapy框架在資料提取和儲存方面的強大功能有了更深入的理解。使用Item和Pipeline的組合,我能夠有效地定義和處理爬取的資料。透過建立Item類,我清晰地規定了要提取的欄位,並在Pipeline中對資料進行進一步處理,比如清洗和儲存。

在實現資料序列化輸出時,我選擇了將股票資訊儲存到MySQL資料庫中。這一過程讓我意識到,將資料儲存與爬取邏輯分離的必要性,使得程式碼更具可維護性。此外,透過XPath選擇器提取資訊,我能靈活地定位網頁元素,從而高效地獲取所需的資料。

在操作MySQL的過程中,我也提升了對資料庫基本操作的理解,比如連線、插入和查詢等。遇到的一些問題,比如資料重複和連線異常,使我學會了如何除錯和最佳化程式碼,提升了我的問題解決能力。

總體而言,本次作業不僅增強了我的爬蟲技術和資料庫管理能力,還讓我認識到資料提取過程中系統性思維的重要性。這對我未來的程式設計實踐和專案開發具有積極的推動作用。

作業③:

要求:熟練掌握 scrapy 中 Item、Pipeline 資料的序列化輸出方法;使用scrapy框架+Xpath+MySQL資料庫儲存技術路線爬取外匯網站資料。
候選網站:中國銀行網:https://www.boc.cn/sourcedb/whpj/
建立完工程後編寫爬蟲程式碼work3.py

點選檢視程式碼
import scrapy
from Practical_work3.items import work3_Item

class Work3Spider(scrapy.Spider):
    name = 'work3'
    start_urls = ['https://www.boc.cn/sourcedb/whpj/']

    def parse(self, response):
        data_lists = response.xpath('//table[@align="left"]/tr')
        for data_list in data_lists:
            datas = data_list.xpath('.//td/text()').getall()
            if len(datas) >= 7:
                item = work3_Item()
                item['name'] = datas[0].strip()
                item['price1'] = datas[1].strip()
                item['price2'] = datas[2].strip()
                item['price3'] = datas[3].strip()
                item['price4'] = datas[4].strip()
                item['price5'] = datas[5].strip()
                item['date'] = datas[6].strip()
                yield item

編寫管道檔案pipelines.py

點選檢視程式碼
import pymysql
from Practical_work3.items import work3_Item


class work3_Pipeline:

    def open_spider(self, spider):
        try:
            self.db = pymysql.connect(host='127.0.0.1', user='root', passwd='Wjh040619@', port=3306, charset='utf8',
                                      database='scrapy')
            self.cursor = self.db.cursor()
            self.cursor.execute('DROP TABLE IF EXISTS bank')
            sql = """CREATE TABLE bank(Currency varchar(32), p1 varchar(17), p2 varchar(17), p3 varchar(17), p4 varchar(17), p5 varchar(17), Time varchar(32))"""
            self.cursor.execute(sql)
        except Exception as e:
            print(f"開啟爬蟲時出錯: {e}")

    def process_item(self, item, spider):
        if isinstance(item, work3_Item):
            try:
                sql = 'INSERT INTO bank VALUES (%s, %s, %s, %s, %s, %s, %s)'
                self.cursor.execute(sql, (
                item['name'], item['price1'], item['price2'], item['price3'], item['price4'], item['price5'],
                item['date']))
                self.db.commit()
            except Exception as e:
                print(f"處理項時出錯: {e}")
        return item

    def close_spider(self, spider):
        self.cursor.close()
        self.db.close()
` 配置items.py滿足輸出內容
點選檢視程式碼
import scrapy

class work3_Item(scrapy.Item):
    name = scrapy.Field()
    price1 = scrapy.Field()
    price2 = scrapy.Field()
    price3 = scrapy.Field()
    price4 = scrapy.Field()
    price5 = scrapy.Field()
    date = scrapy.Field()

在settings.py檔案下增加以下配置

確保管道檔案的正確執行
執行結果:

心得體會

在本次實驗中,我深入學習瞭如何使用Scrapy框架爬取中國銀行網的外匯資料,掌握了Item、Pipeline以及MySQL資料庫的結合使用。這一過程讓我體會到資料爬取的系統性和複雜性。
首先,透過定義Item類,我能夠清晰地表示要爬取的資料結構,例如外匯名稱、匯率和時間等欄位。這種結構化的定義使得資料處理更加有序,並提高了資料的一致性。接著,我在Pipeline中實現了資料的清洗和儲存,確保了只將有效資料存入資料庫中。
使用XPath選擇器提取資料的過程非常直觀,我能夠靈活地獲取網頁中所需的具體資訊。透過分析網頁結構,我迅速定位到外匯資訊,提升了我的資料抓取效率。
在將資料儲存到MySQL資料庫的過程中,我學習瞭如何建立資料庫連線、執行插入操作,以及處理可能出現的異常。這讓我對資料庫操作有了更深入的理解,並提高了我的實際應用能力。
總之,本次實驗不僅讓我掌握了Scrapy框架的基本用法,還提升了我對資料爬取和儲存流程的整體理解。這些經驗將為我未來在資料分析和處理方面的專案奠定堅實的基礎。

相關文章