Python爬蟲實戰:手把手教你爬取農產品數據(附代碼)

来源:https://www.cnblogs.com/python0921/archive/2020/04/25/12775446.html
-Advertisement-
Play Games

前言 文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理。 爬蟲的網站:萬邦國際集團。其成立於2010年,總部位於河南省鄭州市,以“立足三農、保障民生、服務全國”為宗旨,業務涵蓋綜合性農產品冷鏈物流、高效生態農業開發、生鮮連鎖超市、跨境 ...


 

 

前言

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

爬蟲的網站:萬邦國際集團。其成立於2010年,總部位於河南省鄭州市,以“立足三農、保障民生、服務全國”為宗旨,業務涵蓋綜合性農產品冷鏈物流、高效生態農業開發、生鮮連鎖超市、跨境電子商務、進出口貿易等農業全產業鏈。榮獲重點龍頭企業、全國農產品“綜合十強市場”、“星創天地”、全國“萬企幫萬村”精準扶貧先進民營企業等榮譽稱號。目前,集團在中牟縣建設運營的萬邦農產品物流園區,已累計完成投資100億元,占地5000畝,建築面積達350萬平方米。擁有固定商戶6000多家,2017年各類農副產品交易額913億元,交易量1720萬噸,位居全國前列,實現農產品“買全球、賣全國”。

其價格信息查詢為get請求,網頁比較規範,且短期內不會有大的變動,很容易分析,故選擇之。

一、使用request爬取數據

# _*_ coding:utf-8 _*_
# 開發人員:未央
# 開發時間:2020/4/12 16:03
# 文件名:Scrapy_lab1.py
# 開發工具:PyCharm
import csv
import codecs
import requests  # 導入requests包
from bs4 import BeautifulSoup  # 導入bs4包
from datetime import datetime


class Produce:
    price_data = []  # 農產品的價格數據列表
    item_name = ""  # 農產品的類別名

    def __init__(self, category):
        self.item_name = category
        self.price_data = []

    # 讀取某一頁的數據,預設是第一頁
    def get_price_page_data(self, page_index=1):
        url = 'http://www.wbncp.com/PriceQuery.aspx?PageNo=' + str(
            page_index) + '&ItemName=' + self.item_name + '&DateStart=2017/10/1&DateEnd=2020/3/31 '
        strhtml = requests.get(url)  # GET方式,獲取網頁數據
        # print(strhtml.text)
        soup = BeautifulSoup(strhtml.text, 'html.parser')  # 解析網頁文檔
        # print(soup)

        table_node = soup.find_all('table')
        # number = 0
        # for table in table_node:
        #     number += 1
        #     print(number, table)
        all_price_table = table_node[21]  # 獲取含有農產品價錢的table的數據
        # print(all_price_table)
        for tr in all_price_table.find_all('tr'):
            number = 0
            price_line = []
            for td in tr.find_all('td'):
                number += 1
                # print(number, td)
                if number == 1:
                    price_line.append(td.get_text().split())  # 獲取品名
                elif number == 2:
                    price_line.append(td.get_text().split())  # 獲取產地
                elif number == 3:
                    price_line.append(td.get_text().split())  # 獲取規格
                elif number == 4:
                    price_line.append(td.get_text().split())  # 獲取單位
                elif number == 5:
                    price_line.append(td.get_text().split())  # 獲取最高價
                elif number == 6:
                    price_line.append(td.get_text().split())  # 獲取最低價
                elif number == 7:
                    price_line.append(td.get_text().split())  # 獲取均價
                elif number == 8:
                    price_line.append(datetime.strptime(td.get_text().replace('/', '-'), '%Y-%m-%d'))  # 獲取日期
            self.price_data.append(price_line)
        return

    # 獲取全部頁面的數據
    def get_price_data(self):
        for i in range(33):
            self.get_price_page_data(str(i))
        return

    # 講爬蟲的數據寫入到CSV文件,路徑為:D:\Data_pytorch\名字.csv
    def data_write_csv(self):  # file_address為寫入CSV文件的路徑,self.price_data為要寫入數據列表
        self.get_price_data()
        file_address = "D:\Data_pytorch\\" + self.item_name.__str__() + ".csv"
        file_csv = codecs.open(file_address, 'w+', 'utf-8')  # 追加
        writer = csv.writer(file_csv, delimiter=' ', quotechar=' ', quoting=csv.QUOTE_MINIMAL)
        for temp_data in self.price_data:
            writer.writerow(temp_data)
        print(self.item_name + "爬蟲數據保存到文件成功!")

    # 以字典類型讀取csv文件,讀取路徑為:D:\Data_pytorch\名字.csv
    def data_reader_csv(self):
        file_address = "D:\Data_pytorch\\" + self.item_name.__str__() + ".csv"
        with open(file_address, 'r', encoding='utf8')as fp:
            # 使用列表推導式,將讀取到的數據裝進列表
            data_list = [i for i in csv.DictReader(fp, fieldnames=None)]  # csv.DictReader 讀取到的數據是list類型
        print(self.item_name + "數據如下:")
        print(data_list)
        return data_list


list = ["白菜", "包菜", "土豆", "菠菜", "蒜苔"]
for temp_name in list:
    produce = Produce(temp_name)
    produce.data_write_csv()
    data = produce.data_reader_csv()

 

運行之後,文件顯示內容如下:

 

二、使用Scrapy爬取數據

類似之前的學習案例,這裡不再一步一步的介紹,直接上代碼:

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
from scrapy.loader import ItemLoader
from scrapy.loader.processors import TakeFirst


class PriceSpiderItemLoader(ItemLoader):
    # 自定義itemloader,用於存儲爬蟲所抓取的欄位內容的
    default_output_processor = TakeFirst()


class PriceSpiderItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    name = scrapy.Field()  # 品名
    address = scrapy.Field()  # 產地
    norms = scrapy.Field()  # 規格
    unit = scrapy.Field()  # 單位
    high = scrapy.Field()  # 最高價
    low = scrapy.Field()  # 最低價
    price_ave = scrapy.Field()  # 均價
    price_date = scrapy.Field()  # 日期

 

setting.py代碼如下:

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

# Scrapy settings for price_spider project
#
# For simplicity, this file contains only settings considered important or
# commonly used. You can find more settings consulting the documentation:
#
#     https://doc.scrapy.org/en/latest/topics/settings.html
#     https://doc.scrapy.org/en/latest/topics/downloader-middleware.html
#     https://doc.scrapy.org/en/latest/topics/spider-middleware.html
from scrapy.exporters import JsonLinesItemExporter


# 預設顯示的中文是閱讀性較差的Unicode字元
# 需要定義子類顯示出原來的字元集(將父類的ensure_ascii屬性設置為False即可)
class CustomJsonLinesItemExporter(JsonLinesItemExporter):
    def __init__(self, file, **kwargs):
        super(CustomJsonLinesItemExporter, self).__init__(file, ensure_ascii=False, **kwargs)


# 啟用新定義的Exporter類
FEED_EXPORTERS = {
    'json': 'price_spider.settings.CustomJsonLinesItemExporter',
}

BOT_NAME = 'price_spider'

SPIDER_MODULES = ['price_spider.spiders']
NEWSPIDER_MODULE = 'price_spider.spiders'

# Crawl responsibly by identifying yourself (and your website) on the user-agent
# USER_AGENT = 'price_spider (+http://www.yourdomain.com)'

# Obey robots.txt rules
ROBOTSTXT_OBEY = False

# Configure maximum concurrent requests performed by Scrapy (default: 16)
# CONCURRENT_REQUESTS = 32

# Configure a delay for requests for the same website (default: 0)
# See https://doc.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
DOWNLOAD_DELAY = 3

 

爬蟲邏輯(spider.py)代碼如下:

# _*_ coding:utf-8 _*_
# 開發人員:未央
# 開發時間:2020/4/16 14:55
# 文件名:spider.py
# 開發工具:PyCharm
import scrapy
from price_spider.items import PriceSpiderItemLoader, PriceSpiderItem


class SpiderSpider(scrapy.Spider):
    name = 'spider'
    allowed_domains = ['www.wbncp.com']
    start_urls = ['http://www.wbncp.com/PriceQuery.aspx?PageNo=1&ItemName=%e7%99%bd%e8%8f%9c&DateStart=2017/10/1'
                  '&DateEnd=2020/3/31', 'http://www.wbncp.com/PriceQuery.aspx?PageNo=1&ItemName=土豆&DateStart=2017/10/1'
                                        '&DateEnd=2020/3/31', 'http://www.wbncp.com/PriceQuery.aspx?PageNo=1&ItemName'
                                                              '=芹菜&DateStart=2017/10/1 &DateEnd=2020/3/31']

    def parse(self, response):
        item_nodes = response.xpath("//tr[@class='Center' or @class='Center Gray']")
        for item_node in item_nodes:
            item_loader = PriceSpiderItemLoader(item=PriceSpiderItem(), selector=item_node)
            item_loader.add_css("name", "td:nth-child(1) ::text")
            item_loader.add_css("address", "td:nth-child(2) ::text")
            item_loader.add_css("norms", "td:nth-child(3) ::text")
            item_loader.add_css("unit", "td:nth-child(4) ::text")
            item_loader.add_css("high", "td:nth-child(5) ::text")
            item_loader.add_css("low", "td:nth-child(6) ::text")
            item_loader.add_css("price_ave", "td:nth-child(7)::text")
            item_loader.add_css("price_date", "td:nth-child(8)::text")
            price_item = item_loader.load_item()
            yield price_item

        next_page = response.xpath("//*[@id='cphRight_lblPage']/div/a[10]/@href").extract_first()
        if next_page is not None:
            next_page = response.urljoin(next_page)
            yield scrapy.Request(next_page, callback=self.parse)

 

替代運行命令(price_scrapy_main.py)的代碼如下:

# _*_ coding:utf-8 _*_
# 開發人員:未央
# 開發時間:2020/4/16 14:55
# 文件名:price_scrapy_main.py
# 開發工具:PyCharm
from scrapy.cmdline import execute

execute(["scrapy", "crawl", "spider", "-o", "price_data.csv"])

 

運作後,將csv數據導入excel中,結果如下:

 

三、經驗總結:

1.使用request確實比較靈活,但是如果爬取數據多很不方便,代碼也會很長,還是使用scrapy方便。特別是爬取多個頁面,scrapy 的橫向和縱向爬取,超級膩害!

2.Scrapy主要是設置文件(setting.py)的各種設置以及爬蟲文件(本文是spider.py)的爬蟲邏輯,其中主要是選擇器部分比較麻煩

 

如果你處於想學Python或者正在學習Python,Python的教程不少了吧,但是是最新的嗎?說不定你學了可能是兩年前人家就學過的內容,在這小編分享一波2020最新的Python教程。獲取方式,私信小編 “ 資料 ”,即可免費獲取哦!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 【目錄】 一、 threading模塊介紹 二 、開啟線程的兩種方式 三 、在一個進程下開啟多個線程與在一個進程下開啟多個子進程的區別 四、 線程相關的其他方法 五、守護線程 六、Python GIL(Global Interpreter Lock) 八、同步鎖 九、死鎖現象與遞歸鎖 十、線程que ...
  • Golang中存在一個Sync.Pool 對象,從名字上看像是對象池,但他本質上和實際上的對象池有著很大的區別,下麵將詳細介紹該對象。 Sync.Pool對象可伸縮、併發安全; 數據結構 sync.Pool對外暴露Get、Put、New三個方法,Get返回Pool中的對象,當沒有取得到對象時調用Ne ...
  • 直接進入主題需求: (1) 獲取你對象chrome前一天的瀏覽記錄中的所有網址(url)和訪問時間,並存在一個txt文件中 (2)將這個txt文件發送給指定的郵箱地址(你的郵箱) (3)建立例行任務,每天定時自動完成這些操作,你就可以通過郵件查看你對象每天看啥了 這裡要註意:不管你是為了Python ...
  • 定時任務 每天定時執行任務可以使用springboot裡面提供的@Schelduled註解加上cron表達式,但是有一些特殊的任務,比如幾分鐘之後執行,像這類定時任務可以使用Spring Cloud Stream+RabbitMQ來實現 這個首先要下載rabbitmq "插件" 創建boot工程,需 ...
  • Python爬蟲為什麼受歡迎 如果你仔細觀察,就不難發現,懂爬蟲、學習爬蟲的人越來越多,一方面,互聯網可以獲取的數據越來越多,另一方面,像 Python這樣的編程語言提供越來越多的優秀工具,讓爬蟲變得簡單、容易上手。 利用爬蟲我們可以獲取大量的價值數據,從而獲得感性認識中不能得到的信息,這裡要註意: ...
  • python入門介紹 一、編程語言的分類 分類: 機器語言: 用二進位代碼0和1描述的指令稱為機器指令,由於電腦內部是基於二進位指令工作的,所以機器語言是直接控制電腦硬體 彙編語言: 彙編語言的實質和機器語言是相同的,都是直接對硬體操作,只不過指令採用了英文縮寫的標識符,更容易識別和記憶 高級語 ...
  • 編程語言及電腦介紹 一、編程語言是什麼 語言其實就是人與人之間溝通的介質/工具,比如英語、法語等 而編程語言則是人與電腦之間溝通的介質,常見的編程語言有python、java、php、.net等 二、為什麼要編程 編程就是人把自己想電腦做的事,也就是自己的思維邏輯,用編程語言表達出來 編程的目 ...
  • 1 package com.yhqtv.demo01Exception; 2 /* 3 * 一、異常體繫結構 4 *java.lang.Throwable 5 * java.lang.Error:一般不編寫針對性的代碼進行處理。 6 * java.lang.Exception:可以進行異常的處理 7 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...