【0基礎學爬蟲】爬蟲基礎之scrapy的使用

【0基礎學爬蟲】爬蟲基礎之scrapy的使用

7gJDd5.png

大數據時代,各行各業對數據采集的需求日益增多,網絡爬蟲的運用也更為廣泛,越來越多的人開始學習網絡爬蟲這項技術,K哥爬蟲此前已經推出不少爬蟲進階、逆向相關文章,為實現從易到難全方位覆蓋,特設【0基礎學爬蟲】專欄,幫助小白快速入門爬蟲,本期為自動化工具 Selenium 的使用。

scrapy簡介

Scrapy 是一個用于爬取網站并提取結構化數據的強大且靈活的開源框架。它提供了簡單易用的工具和組件,使開發者能夠定義爬蟲、調度請求、處理響應并存儲提取的數據。Scrapy 具有高效的異步處理能力,支持分布式爬取,通過其中間件和擴展機制可以方便地定制和擴展功能,廣泛應用于數據挖掘、信息聚合和自動化測試等領域。

scrapy 工作流程

7gJSwm.png

1、啟動爬蟲:Scrapy 啟動并激活爬蟲,從初始URL開始爬取。
2、調度請求:爬蟲生成初始請求,并將其發送給調度器。
3、下載頁面:調度器將請求發送給下載器,下載器從互聯網獲取頁面。
4、處理響應:下載器將響應返回給引擎,傳遞給爬蟲。
5、提取數據:爬蟲從響應中提取數據(items)和更多的URL(新的請求)。
6、處理數據:提取的數據通過項目管道進行處理,清洗并存儲。
7、繼續爬取:新的請求被調度器處理,繼續下載和提取數據,直到所有請求處理完畢。

scrapy 每個模塊的具體作用

7gJUO4.png

安裝scrapy

pip install scrapy

安裝成功后,直接在命令終端輸入 scrapy ,輸出內容如下:

7gJ1ih.png

新建scrapy項目

使用 scrapy startproject + 項目名 創建新項目。

這里我們使用 scrapy startproject scrapy_demo 創建項目示例:

7gJYVY.png

然后通過下面命令創建我們的爬蟲模板,這里就按照scrapy 給出的實例創建:

cd scrapy_demo
scrapy genspider example example.com

使用pycharm 打開我們的項目,項目格式如下:

7gJR79.png

各個文件夾的含義:

spiders:存放爬蟲文件
items:定義爬取的數據結構
middlewares:定義下載中間件和爬蟲中間件。中間件是處理請求和響應的鉤子,可以修改請求、響應、異常等
pipelines:定義管道,用于處理爬蟲提取的數據,例如數據清洗、驗證和存儲等操作。
settings:定義了項目的基本配置

使用scrapy

這里以我們熟悉的某瓣為例來說明 scrapy 的用法。

修改 example.py 文件:

import scrapyclass ExampleSpider(scrapy.Spider):name = "example"# allowed_domains = ["example.com"]   # 允許爬取的網站范圍,可以不要start_urls = ["https://movie.douban.com/top250"]def parse(self, response):print(response.text)

在終端輸入 scrapy crawl example 運行結果如下:

7gJrXH.png

輸出了很多信息,包含版本號、插件、啟用的中間件等信息。

Versions:版本信息,包括scrapy和其它庫的版本信息
Overridden settings: 重寫的相關配置
Enabled downloader middlewares:開啟的下載器中間件
Enabled spider middlewares:開啟的爬蟲中間件
Enabled item pipelines:開啟的管道
Telnet Password:Telnet 平臺密碼(Scrapy附帶一個內置的telnet控制臺,用于檢查和控制Scrapy運行過程)
Enabled extensions :開啟的拓展功能
Dumping Scrapy stats:所以的信息匯總

我們重點看這里:

7gJ4hU.png

可以發現,我們返回了403狀態碼,原因是因為我們少了請求頭和有robots協議。

在 setting.py 增加請求頭、修改 robots 協議:

# Obey robots.txt rules
ROBOTSTXT_OBEY = False   # 這里改成False,表示不遵守robots協議# Override the default request headers:
DEFAULT_REQUEST_HEADERS = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","Accept-Language": "en","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0"
}  # 然后把這個放開,這個表示該項目的默認請求頭

運行之后,可以發現能正常返回 html 頁面數據。

scrapy 運行項目的兩種方式

上面我們是通過終端運行的,下面我們使用 python 運行。

修改 example.py 文件代碼:

import scrapy
from scrapy import cmdlineclass ExampleSpider(scrapy.Spider):name = "example"# allowed_domains = ["example.com"]   # 允許爬取的網站范圍,可以不要start_urls = ["https://movie.douban.com/top250"]def parse(self, response):print(response.text)if __name__ == '__main__':cmdline.execute("scrapy crawl example".split())# cmdline.execute("scrapy crawl example --nolog".split()) 不輸出提示信息

如果不想輸出與爬蟲無關的信息,可以在后面加上 --nolog 命令,這樣就不會打印提示信息了。

數據翻頁抓取

scrapy實現翻頁請求

我們可以直接利用scrapy 內置的數據解析方法對數據進行抓取:

代碼如下:

import scrapy
from scrapy import cmdlineclass ExampleSpider(scrapy.Spider):name = "example"# allowed_domains = ["example.com"]   # 允許爬取的網站范圍,可以不要start_urls = ["https://movie.douban.com/top250"]def parse(self, response):print(response.text)ol_list = response.xpath('//ol[@class="grid_view"]/li')for ol in ol_list:item = {}# 利用scrapy封裝好的xpath選擇器定位元素,并通過extract()或extract_first()來獲取結果item['title'] = ol.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()item['rating'] = ol.xpath('.//div[@class="bd"]/div/span[2]/text()').extract_first()item['quote'] = ol.xpath('.//div[@class="bd"]//p[@class="quote"]/span/text()').extract_first()print(item)if __name__ == '__main__':cmdline.execute("scrapy crawl example --nolog".split())# cmdline.execute("scrapy crawl example".split())

上面只抓取到了第一頁,那么我們怎么抓取后面的每一頁呢?

這里介紹兩種方式:

1、利用callback 參數,進入項目源碼,找到Request請求對象:

7gJCrq.png

Request 對象含義如下:

參數描述
url (str)請求的 URL。
callback (callable)用于處理該請求的回調函數。默認是 parse 方法。
method (str)HTTP 請求方法,如 'GET', 'POST' 等。默認為 'GET'
headers (dict)請求頭信息。
body (bytes or str)請求體,通常在 POST 請求中使用。
cookies (dict or list)請求攜帶的 Cookies,可以是一個字典或字典的列表。
meta (dict)該請求的元數據字典,用于在不同請求之間傳遞數據。
encoding (str)請求的編碼格式。默認為 'utf-8'
priority (int)請求的優先級,默認值為 0。優先級值越高,優先級越高。

callback 就是回調函數,接收一個函數名為參數。

實現如下:

def parse(self, response):print(response.text)ol_list = response.xpath('//ol[@class="grid_view"]/li')for ol in ol_list:item = {}# extract_first() 提取第一個元素item['title'] = ol.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()item['rating'] = ol.xpath('.//div[@class="bd"]/div/span[2]/text()').extract_first()item['quote'] = ol.xpath('.//div[@class="bd"]//p[@class="quote"]/span/text()').extract_first()print(item)if response.xpath("//a[text()='后頁>']/@href").extract_first() is not None:next_url = response.urljoin(response.xpath("//a[text()='后頁>']/@href").extract_first())print(next_url)yield scrapy.Request(url=next_url, callback=self.parse)

2、重寫 start_requests 方法:

7gJJds.png

代碼如下:

    def start_requests(self):for i in range(0, 5):url = 'https://movie.douban.com/top250?start={}&filter='.format(i * 25)yield scrapy.Request(url)def parse(self, response):ol_list = response.xpath('//ol[@class="grid_view"]/li')for ol in ol_list:item = {}# extract_first() 提取第一個元素item['title'] = ol.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()item['rating'] = ol.xpath('.//div[@class="bd"]/div/span[2]/text()').extract_first()item['quote'] = ol.xpath('.//div[@class="bd"]//p[@class="quote"]/span/text()').extract_first()print(item)

Responses 對象含義如下:

參數描述
url (str)響應的 URL。
status (int)HTTP 響應狀態碼。
headers (dict)響應頭信息。
body (bytes)響應體內容,二進制格式。
flags (list)響應的標志列表。
request (Request)生成此響應的請求對象。
meta (dict)該請求的元數據字典,用于在不同請求之間傳遞數據。
encoding (str)響應的編碼格式。通常由 Scrapy 自動檢測,但可以手動設置。
text (str)響應體內容,解碼為字符串格式。
css (callable)選擇器,用于通過 CSS 表達式提取數據。
xpath (callable)選擇器,用于通過 XPath 表達式提取數據。
json (callable)解析 JSON 響應體并返回字典或列表。

數據定義

數據爬取下來之后,我們通過scrapy 的 items 進行操作。item就是即提前規劃好哪些字段需要抓取,比如上面的標題、評分這些字段就需要使用 item 提前定義好。

Scrapy Item 的作用

  1. 結構化數據:通過定義 Item,可以明確抓取數據的結構。例如,一個商品的信息可能包含名稱、價格、庫存等字段。
  2. 數據驗證:可以在 Item 中定義字段的類型和驗證規則,確保抓取的數據符合預期。
  3. 代碼可讀性:通過定義 Item,可以使代碼更具可讀性和可維護性,清晰地了解抓取的數據結構。

定義item

item.py 編寫如下:

import scrapyclass ScrapyDemoItem(scrapy.Item):# define the fields for your item here like:# name = scrapy.Field()title = scrapy.Field()rating = scrapy.Field()quote = scrapy.Field()

使用item

使用 item 需要先實例化,使用方法和 python 字典方式一樣

在example.py 導入我們需要使用的 item 類,這里我們就用默認的 ScrapyDemoItem 類

import scrapy  
from scrapy import cmdline
from scrapy_demo.items import ScrapyDemoItemclass ExampleSpider(scrapy.Spider):name = "example"def start_requests(self):for i in range(0, 5):url = 'https://movie.douban.com/top250?start={}&filter='.format(i * 25)yield scrapy.Request(url)def parse(self, response):ol_list = response.xpath('//ol[@class="grid_view"]/li')for ol in ol_list:item = ScrapyDemoItem()# extract_first() 提取第一個元素item['title'] = ol.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()item['rating'] = ol.xpath('.//div[@class="bd"]/div/span[2]/text()').extract_first()item['quote'] = ol.xpath('.//div[@class="bd"]//p[@class="quote"]/span/text()').extract_first()print(item)if __name__ == '__main__':cmdline.execute("scrapy crawl example --nolog".split())

數據存儲

Scrapy Pipeline 的作用

  1. 數據清洗和驗證:你可以在 pipeline 中編寫代碼來清洗和驗證數據。例如,去除空白字符、處理缺失值、驗證數據格式等。
  2. 去重:可以檢查和去除重復的數據項,確保最終的數據集是唯一的。
  3. 存儲:將處理過的數據存儲到不同的存儲后端,如數據庫(MySQL、MongoDB)
  4. 進一步處理:執行復雜的轉換、聚合等操作,以便在存儲之前對數據進行進一步處理。

編寫Pipeline

這里我們使用mysql 進行數據保存。

pipeline.py

import pymysql
from itemadapter import ItemAdapter
class MysqlPipeline:def __init__(self):self.connection = pymysql.connect(user='root',  # 換上你自己的賬密和數據庫 password='root', db='scrapy_demo',)self.cursor = self.connection.cursor()self.create_table()def create_table(self):table = """CREATE TABLE IF NOT EXISTS douban (id INT AUTO_INCREMENT PRIMARY KEY,title VARCHAR(255) NOT NULL,rating FLOAT NOT NULL,quote TEXT)CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"""self.cursor.execute(table)self.connection.commit()def process_item(self, item, spider):try:self.cursor.execute("INSERT INTO douban(id,title, rating, quote) VALUES (%s,%s, %s, %s)",(0, item['title'], item['rating'], item['quote']))self.connection.commit()except pymysql.MySQLError as e:spider.logger.error(f"Error saving item: {e}")print(e)return itemdef close_spider(self, spider):self.cursor.close()self.connection.close()

settings.py

ITEM_PIPELINES = {"scrapy_demo.pipelines.MysqlPipeline": 300,
}  # 放開Item 

配置好后,運行example 就能看到我們的數據被正確入庫了。

數據不止能存儲mysql,還存儲到mongo、csv等等,感興趣的小伙伴可以查看官方文檔,有很詳細的教程。

scrapy 中間件

scrapy中間件的分類和作用

根據scrapy運行流程中所在位置不同分為:

  1. 下載中間件
  2. 爬蟲中間件

Scrapy 中間件 (middlewares) 的作用是處理 Scrapy 請求和響應的鉤子(hook),允許你在它們被scrapy引擎處理前或處理后對它們進行處理和修改。中間件為用戶提供了一種方式,可以在請求和響應的不同階段插入自定義邏輯。

一般我們常用的是下載中間件,所以下面我們用下載中間件來說明用法。

middlewares.py

Downloader Middlewares默認的方法:- process_request(self, request, spider)- 當每個request通過下載中間件時,該方法被調用。- 返回None值:繼續請求- 返回Response對象:不再請求,把response返回給引擎- 返回Request對象:把request對象交給調度器進行后續的請求
- process_response(self, request, response, spider)- 當下載器完成http請求,傳遞響應給引擎的時候調用- 返回Resposne:交給process_response來處理- 返回Request對象:交給調取器繼續請求
- from_crawler(cls, crawler):- 類似于init初始化方法,只不過這里使用的classmethod類方法- 可以直接crawler.settings獲得參數,也可以搭配信號使用

自定義隨機ua

我們借助 feapder 給我們封裝好的 ua 來進行測試:

middlewares.py

from feapder.network import user_agent
class ScrapyDemoDownloaderMiddleware:def process_request(self, request, spider):request.headers['User-Agent'] = user_agent.get()return None

settings.py

DOWNLOADER_MIDDLEWARES = {"scrapy_demo.middlewares.ScrapyDemoDownloaderMiddleware": 543,
} #放開下載中間件

example.py

import scrapy
from scrapy import cmdlineclass ExampleSpider(scrapy.Spider):name = "example"start_urls = ["https://movie.douban.com/top250"]def parse(self, response):print(response.request.headers)if __name__ == '__main__':cmdline.execute("scrapy crawl example --nolog".split())

可以發現每次輸出的 ua 不一樣。

自定義代理

通過Request 對象的 mata 參數來設置代理,這里以本地的 7890 端口為例:

middlewares.py

    def process_request(self, request, spider):request.headers['User-Agent'] = user_agent.get()request.meta['proxy'] = "http://127.0.0.1:7890"return None

中間件權重

當涉及到多個中間件的時候,請求時數字越小權重越高,越先執行 ,響應時數字越大越先執行。這里我們可以借助scrapy 流程圖來理解,誰離scrapy engine 引擎越近,表明權重越高。

這里我們創建兩個類來測試一下:

middlewares.py

class OneMiddleware(object):def process_request(self, request, spider):print('one 請求')def process_response(self, request, response, spider):print('one 響應')# return Noneclass TwoMiddleware(object):def process_request(self, request, spider):print('two 請求')def process_response(self, request, response, spider):print('two 響應')return response

settings.py

DOWNLOADER_MIDDLEWARES = {"scrapy_demo.middlewares.OneMiddleware": 543,"scrapy_demo.middlewares.TwoMiddleware": 544
}

運行 example.py 輸出如下結果:

7gJnS7.png

scrapy-redis 組件

Scrapy-Redis 是 Scrapy 的一個擴展,允許你使用 Redis 作為爬蟲隊列,并共享爬蟲狀態:

7gJIiI.png

安裝

pip install scrapy-redis
注意:這里scrapy 版本需要替換成 2.9.0版本或者2.0.0以下,不然會報錯:
TypeError: crawl() got an unexpected keyword argument 'spider'
因為新版本已經不支持了。

然后新建 一個 redis_demo 爬蟲

scrapy genspider redis_demo  redis_demo.com

配置 scrapy-redis

settings.py

加入下面代碼
# 設置 Redis 主機和端口
REDIS_URL = 'redis://127.0.0.1:6379/0'
# 使用 Scrapy-Redis 的調度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"# 使用 Scrapy-Redis 的去重器
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"開啟redis管道
ITEM_PIPELINES = {"scrapy_redis.pipelines.RedisPipeline": 301
}

redis_demo.py

from scrapy_redis.spiders import RedisSpider
from scrapy import cmdline# 繼承scrapy——redis 類,實現分布式
class RedisDemoSpider(RedisSpider):name = "redis_demo"redis_key = "redis_demo:start_urls"  # redis keydef parse(self, response):ol_list = response.xpath('//ol[@class="grid_view"]/li')for ol in ol_list:item = {}# extract_first() 提取第一個元素item['title'] = ol.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()item['rating'] = ol.xpath('.//div[@class="bd"]/div/span[2]/text()').extract_first()item['quote'] = ol.xpath('.//div[@class="bd"]//p[@class="quote"]/span/text()').extract_first()print(item)yield itemif __name__ == '__main__':cmdline.execute("scrapy crawl redis_demo".split())

運行后會發現已經在監聽端口了:

7gJf7V.png

這時我們新建一個demo 文件:

import redisr = redis.Redis(db=0)
r.lpush('redis_demo:start_urls',"https://movie.douban.com/top250")
#r.lpush('redis_demo:start_urls',"https://movie.douban.com/top250?start=25&filter=")

然后運行這個demo.py文件,會發現數據已經成功入庫了:

7gJiWL.png

我們打開redis 可視化工具進行查看:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

但是現在當我們每次跑一個地址的時候,原來的數據就沒有了,要想解決這個問題,我們就得運用到scrapy-redis的持久化存儲了。

redis 持久化存儲

Scrapy-Redis 默認會在爬取全部完成后清空爬取隊列和去重指紋集合。初始第一個網址一定會進行請求,后面的重復方式不會進行請求。

如果不想自動清空爬取隊列和去重指紋集合,我們在 settings.py 增加如下配置:

SCHEDULER_PERSIST = True   #如果需要持久化爬取狀態,可以開啟

再次運行 redis_demo.py ,然后運行兩次demo.py文件可以測試一下:

7gJsXJ.png

至此,完成了持久化存儲。

redis 分布式

要想在多臺電腦跑同一個程序,只需要把其它電腦的 redis 連接到一臺就行。

settings.py
# 設置 Redis 主機和端口
REDIS_URL = '這里寫你的遠程電腦ip地址'
# 使用 Scrapy-Redis 的調度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"# 使用 Scrapy-Redis 的去重器
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"開啟redis管道
ITEM_PIPELINES = {"scrapy_redis.pipelines.RedisPipeline": 301
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/37641.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/37641.shtml
英文地址,請注明出處:http://en.pswp.cn/web/37641.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

武漢星起航:亞馬遜精選,中國賣家打造的時尚防雨裝備推薦

炎炎夏日,突如其來的雨水成為了許多城市居民的“常客”。在這樣的季節里,一套時尚又實用的防雨裝備成為了人們出行的必備之選。中國賣家在亞馬遜上的防雨裝備選品,憑借其精湛的工藝和獨特的設計理念,成為了消費者們的首選。 首先…

云端企業協同:iCloud與企業應用集成全攻略

云端企業協同:iCloud與企業應用集成全攻略 在數字化轉型的浪潮中,企業應用正迅速遷移到云端,以提高效率、降低成本并增強競爭力。iCloud作為蘋果公司提供的云服務,不僅深受個人用戶喜愛,也為企業提供了一系列強大的集…

選哪個短劇系統源碼好:全面評估與決策指南

在短劇內容創作和分享日益流行的今天,選擇合適的短劇系統源碼對于構建一個成功的短劇平臺至關重要。短劇系統源碼不僅關系到平臺的穩定性和用戶體驗,還直接影響到內容創作者和觀眾的互動質量。本文將提供一份全面的評估指南,幫助您在眾多短劇…

CesiumJS【Basic】- #037 繪制輪廓線(Entity方式)

文章目錄 繪制輪廓線(Entity方式)1 目標2 代碼2.1 main.ts繪制輪廓線(Entity方式) 1 目標 使用Entity方式繪制輪廓線 2 代碼 2.1 main.ts import * as Cesium from cesium;const viewer = new Cesium.Viewer(<

互聯網產品經理的薪資是多少?你拖后腿了嗎?

互聯網產品經理作為現代互聯網行業中的核心角色&#xff0c;其薪資水平一直備受關注。然而&#xff0c;由于地區、公司規模、個人經驗等多個因素的影響&#xff0c;互聯網產品經理的年薪差異較大。本文將從多個角度對互聯網產品經理的年薪進行分析&#xff0c;并給出具體數據。…

奔馳G350升級原廠自適應懸掛系統有哪些作用

奔馳 G350 升級自適應懸掛系統后&#xff0c;可根據行車路況自動調整懸架高度和彈性&#xff0c;從而提升駕乘的舒適性和穩定性。 這套系統的具體功能包括&#xff1a; ? 多種模式選擇&#xff1a;一般有舒適、彎道、運動及越野等模式。例如&#xff0c;彎道模式在過彎時能為…

SSM泰華超市商品管理系統-計算機畢業設計源碼11946

目 錄 摘要 1 緒論 1.1 研究背景 1.2 研究意義 1.3論文結構與章節安排 2系統分析 2.1 可行性分析 2.2 系統流程分析 2.2.1 數據新增流程 3.2.2 數據刪除流程 2.3 系統功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系統用例分析 2.5本章小結 3 系統總體設…

怎么采集天貓的商品或店鋪數據

怎么使用簡數采集器批量采集天貓的商品或店鋪相關信息呢&#xff1f; 簡數采集器暫時不支持采集天貓的商品或店鋪相關數據&#xff0c;只能采集頁面公開顯示的信息&#xff0c;謝謝。 簡數采集器抓取網頁數據特別簡單&#xff0c;不需要懂技術寫代碼&#xff0c;只需填寫網址…

ubuntu22.04 操作系統安裝 Git LFS

在 Ubuntu 22.04 操作系統上安裝 Git Large File Storage (LFS) 的詳細步驟如下&#xff1a; 步驟 1&#xff1a;更新系統軟件包列表 首先&#xff0c;更新系統的軟件包列表&#xff1a; sudo apt-get update步驟 2&#xff1a;安裝 Git 確保你已經安裝了 Git。如果沒有安裝…

Spring 案例

1.完成Account類中的定義私有變量&#xff08;id,userName,balance) // com.spring.jdbc.JdbcTemplate; private Integer id; private String userName; private Double balance;2.完成AccountManage接口類&#xff0c;定義接口&#xff08;插入add、更新update、查詢單個que…

第七十一:數組去重(每用過一個方法就會持續更新。。。)

1.雙層for循環 export const getArr function(arr){ for(var i0;i<arr.length;i){for(var ji1;j<arr.length;j){if(arr[i].indexId arr[j].indexId){arr.splice(j,1)j--}}}return arr;}

基于單片機的 LED 花樣照明時鐘設計

摘要 &#xff1a; 本設計是基于單片機的 LED 花樣照明 &#xff0c; 并附加時鐘設計 . 單片機也叫微控制器 &#xff08; Micro Control Unit, 簡稱 MCU &#xff09;&#xff0c; 因其價格低廉 &#xff0c; 功能強大 &#xff0c; 在實際應用中得到廣泛認可 . 本設計…

高效、便捷的游戲代理結算方案,Xinstall讓您的業務更上一層樓!

隨著游戲行業的蓬勃發展&#xff0c;越來越多的企業和個人開始涉足游戲代理領域。然而&#xff0c;在這個充滿機遇與挑戰的市場中&#xff0c;游戲代理結算問題成為了許多代理商和開發者頭疼的難題。繁瑣的結算流程、復雜的費用計算以及資金安全問題&#xff0c;都讓游戲代理結…

PHP語言學習02

好久不見&#xff0c;學如逆水行舟&#xff0c;不進則退&#xff0c;真是這樣。。。突然感覺自己有點廢。。。 <?php phpinfo(); ?> 新生第一個代碼。 要想看到運行結果&#xff0c;打開瀏覽器&#xff08;127.0.0.1/start/demo01.php&#xff09; 其中&#xff0c…

django @login_required 為什么會自動重定向到/accounts/login/?next=/myblog/post/new/

在Django中&#xff0c;login_required 裝飾器用于確保用戶在訪問某個視圖時已經登錄。如果用戶未登錄&#xff0c;那么Django會自動重定向用戶到登錄頁面。默認情況下&#xff0c;Django使用/accounts/login/作為登錄URL。如果用戶試圖訪問一個需要登錄的視圖&#xff0c;比如…

proto文件應該如何撰寫

什么是.pb.h 和 .pb.cc 文件&#xff1f; protobuf的核心是一個.proto文件&#xff0c;我們自定義一個.proto來創建我們的協議數據&#xff0c;然后使用protocol buffer 編譯器工具編譯生成兩個"文件名.pb.cc"和"文件名.pb.h"的文件。 Protocol Buffers&…

K-Planes代碼記錄

隨記 原文 K-Planes: Explicit Radiance Fields in Space, Time, and Appearance&#xff0c;又要換baseline&#xff0c;可是效果不好能怎么辦呢&#xff0c;我可不可以發瘋。k-planes的代碼又是非常工程瑣碎的&#xff0c;大佬的代碼果然不顧小白死活。隨便記錄下整個過程。…

制造型企業生產管理的技巧,你都用過哪些?

作為管理者&#xff0c;一談到生產管理&#xff0c;你可能會想到很多生產過程中的問題&#xff1a;訂單準交率不高、計劃達成率不高、生產效率低、再制品太多、生產周期長等等一系列問題&#xff1b;如果你不僅僅是一名管理者&#xff0c;你還是一名企業主&#xff0c;你甚至經…

實踐Go的命令模式

簡介 現在的軟件系統往往是分層設計。在業務層執行一次請求時&#xff0c;我們很清楚請求的上下文&#xff0c;包括&#xff0c;請求是做什么的、參數有哪些、請求的接收者是誰、返回值是怎樣的。相反&#xff0c;基礎設施層并不需要完全清楚業務上下文&#xff0c;它只需知道…