scrapy的簡單使用以及相關設置屬性的介紹


0. 楔子(一個最簡單的案例)

 

1.scrapy.Spider

scrapy.spiders.Spider

name

allowed_domains

start_urls

custom_settings

:在爬蟲運行時用這個屬性里的設置覆蓋默認設置,它本身是字典格式的。

Crawler

該屬性在初始化類之后由from_crawler()類方法設置,並鏈接到此蜘蛛實例綁定到的Crawler對象。

爬蟲程序在項目中封裝了大量的組件,用於單一入口訪問(例如擴展,中間件,信號管理器等)。 請參閱Crawler API以了解更多關於它們的信息

Settings

這個爬蟲的設置

Logger

日志

from_crawler(crawler*args**kwargs)

創建自己的爬蟲,一般不需要重寫,默認設置在scrapy.spider._init_py里。

start_requests()

返回一個生成器,用來發送爬取請求。Start_url[]中的url地址會默認的調用這個函數發送網頁爬取請求。

parse(response)

解析響應,從返回的網頁響應中提取數據。

log(message[, levelcomponent])

設置爬蟲的日志,

closed(reason)

關閉爬蟲

2.CrawlSpider

scrapy.spiders.CrawlSpider

相較於spider.Spider它提供rules對象以便爬取跟隨連接,實現多級爬蟲

Rules對象定義如下,爬蟲根據rules定義的規則爬取網站,多個規則匹配同一條連接的時候按照順序只輸出第一條連接。

parse_start_url(response)

處理響應,返回一個Item或者request,或者一個包含兩者的可迭代對象。

Rules類定義如下

Class scrapy.spiders.Rule(link_extractorcallback=Nonecb_kwargs=Nonefollow=None,process_links=Noneprocess_request=None)

link_extractor是連接提取器類,提取需要的鏈接。

Callback回調函數,解析或者爬取每一條提取出來的鏈接,返回一個Item/response列表,或者一個同時包括兩者的列表。

Cb_kwargs回調函數字典類型的參數

Follow 對通過這個規則抽取出來的鏈接是否跟進,如果沒有回調函數,默認為True,否則默認為False

Process-links是一個函數或則一個爬蟲的名字,對提取出來的鏈接起一個過濾的作用。

Eg:

import scrapy

from scrapy.spiders import CrawlSpider, Rule

from scrapy.linkextractors import LinkExtractor

 

class MySpider(CrawlSpider):

    name = 'example.com'

    allowed_domains = ['example.com']

    start_urls = ['http://www.example.com']

 

    rules = (

        # Extract links matching 'category.php' (but not matching 'subsection.php')

        # and follow links from them (since no callback means follow=True by default).

        Rule(LinkExtractor(allow=('category\.php', ), deny=('subsection\.php', ))),

 

        # Extract links matching 'item.php' and parse them with the spider's method parse_item

        Rule(LinkExtractor(allow=('item\.php', )), callback='parse_item'),

    )

 

    def parse_item(self, response):

        self.logger.info('Hi, this is an item page! %s', response.url)

        item = scrapy.Item()

        item['id'] = response.xpath('//td[@id="item_id"]/text()').re(r'ID: (\d+)')

        item['name'] = response.xpath('//td[@id="item_name"]/text()').extract()

        item['description'] = response.xpath('//td[@id="item_description"]/text()').extract()

        return item

2.XMLFeedSpider

scrapy.spiders.XMLFeedSpider

主要用來爬取XML網頁

3. CSVFeedSpider

主要用來解析CSF網頁

4. SitemapSpider

scrapy.spiders.SitemapSpider

解析網站的robots.txt規則,建立網站地圖,實現整站爬取(這個整站爬取是被動的,即你必須知道robots,或提前輸入關於這個網站需要爬取的鏈接)

sitemap_urls一個需要爬取的url地址的列表

sitemap_rules一個存放爬取規則的列表,爬取規則為一個元組(regex, callback)

sitemap_follow所爬取的url地址所共同匹配的正則表達式列表

sitemap_alternate_links如果為真,取回除語言外完全相同的網址,如http://example.com/en

,默認為假。

5. 選擇器:

Eg:

同時,選擇器可以使用正則表達式

 

3.Item

將非結構化的數據變成結構化數據,

classscrapy.item.Item([arg])中聲明

使用條目裝載機裝載條目,

Eg:

 

 

 

3. Item Pipeline

classscrapy.loader.ItemLoader([itemselectorresponse, ]**kwargs)

當爬蟲爬取一個條目時,這個條目將被發送到項目管道,通過依次執行的幾個組件處理數據,每個管道組件(有時也稱為“管道”)是一個實現簡單方法的Python類。

項目管道的典型用途是:

  • 獲取干凈的HTML數據
  • 驗證爬取的數據(檢查項目是否包含某些字段)
  • 檢查重復(並刪除它們)
  • 將爬取的項目存儲在數據庫中

每個項目管道組件是一個Python類,必須實現process_item(selfitemspider)方法:

process_item(selfitemspider):返回一個字典或者一個Item類或者或者一個twited deferred(https://twistedmatrix.com/documents/current/core/howto/defer.html)對象或者一個異常。

Spider與item是對應的關系。

open_spider(selfspider):當spider開始運行時,運行這個函數

close_spider(selfspider)

from_crawler(clscrawler)如果存在,則調用此類方法從Crawler創建管道實例。 它必須返回一個新的管道實例。 抓取對象提供對所有Scrapy核心組件的訪問,如設置和信號; 這是管道訪問它們並將其功能掛接到Scrapy的一種方式

Eg

異常:

 

存儲到json:

 

存儲到MongoDB

 

去重:

假設ID唯一

 

4.Requests

Class scrapy.http.Request(url[, callbackmethod='GET'headersbodycookiesmetaencoding='utf-8'priority=0dont_filter=Falseerrbackflags])

由spider產生發送到downloader

 

避免與現有cookies合並

 

priority (int)設置爬取的優先級,默認是0;

dont_filter(boolean)參數為true是表示這個請求不應該被調度器過濾掉。 當您想要多次執行相同的請求時使用此選項,以忽略重復過濾器。 小心使用它,否則你將進入爬行循環。 默認為False。

errback (callable)異常處理函數

flags (list):發送到請求的標志可用於日志記錄或類似的目的。

Request.meta special keysRequest.meta屬性可以包含任意的數據,但是Scrapy和它的內置擴展可以識別一些特殊的鍵。

Those are:

  • · dont_redirect
  • · dont_retry
  • · handle_httpstatus_list
  • · handle_httpstatus_all
  • · dont_merge_cookies (see cookies parameter of Request constructor)
  • · cookiejar
  • · dont_cache
  • · redirect_urls
  • · bindaddress
  • · dont_obey_robotstxt
  • · download_timeout
  • · download_maxsize
  • · download_latency
  • · download_fail_on_dataloss
  • · proxy
  • · ftp_user (See FTP_USER for more info)
  • · ftp_password (See FTP_PASSWORD for more info)
  • · referrer_policy
  • · max_retry_times

class scrapy.http.FormRequest(url[formdata...])

requests的子類,主要用於表單處理

類方法:

from_response(response[, formname=None, formid=None, formnumber=0,formdata=None, formxpath=None, formcss=None, clickdata=None, dont_click=False, ...])

返回一個新的FormRequest對象,其表單字段值預填充在給定響應中包含的HTML <form>元素中。 有關示例,模擬用戶登錄。

 

該策略默認情況下會自動模擬任何可點擊的表單控件(如<input type =“submit”>)的點擊。 即使這是相當方便的,而且往往是所期望的行為,有時它可能會導致難以調試的問題。 例如,處理使用javascript填充和/或提交的表單時,默認的from_response()行為可能不是最合適的。 要禁用此行為,可以將dont_click參數設置為True。 另外,如果你想改變點擊的控件(而不是禁用它),你也可以使用clickdata參數。

參數:

  • response (Response object) – 該響應包含將用於預填充表單字段的HTML表單
  • formname (string) – 如果給定,將使用具有設置為此值的name屬性的形式。
  • formid (string) – 如果給定,將使用具有設置為此值的id屬性的形式。
  • formxpath (string) – 如果給定,將使用與xpath匹配的第一個表單。
  • formcss (string) – 如果給定,將使用與css選擇器匹配的第一個表單。
  • formnumber (integer) – 要使用的表單的數量,當響應包含多個表單時。第一個(也是默認值)是 0。
  • formdata (dict) – 字段在表單數據中覆蓋。如果響應 <form> 元素中已存在字段,則其值將被在此參數中傳遞的值覆蓋。
  • clickdata (dict) – 屬性來查找單擊的控件。如果沒有提供,表單數據將被提交,模擬第一個可點擊元素的點擊。除了html屬性,控件可以通過其相對於窗體中其他提交表輸入的基於零的索引,通過 nr 屬性來標識。
  • dont_click (boolean) – 如果為True,表單數據將在不點擊任何元素的情況下提交。

5.response

class scrapy.http.Response(url[, status=200, headers=None, body=b'', flags=None, request=None])

urljoin(url):可以將相對url地址結合成絕對url地址

follow(urlcallback=Nonemethod='GET'headers=Nonebody=Nonecookies=Nonemeta=None,encoding='utf-8'priority=0dont_filter=Falseerrback=None)

返回請求實例以跟隨鏈接url。 它接受與Request .__ init__方法相同的參數,但是url可以是相對URL或scrapy.link.Link對象,不僅是絕對URL。

除了絕對/相對URL和鏈接對象,TextResponse提供了一個支持選擇器的follow()方法,這個兩個函數可以用來翻頁。

Eg:

Urljoin

 

Follow()

 

classscrapy.http.TextResponse(url[, encoding[, ...]])response的子類,增加了編碼功能。

新的屬性有:

TextResponse body, as unicode.

Encoding與此響應編碼的字符串。 通過嘗試以下機制來解決編碼問題:

10.1 在構造函數編碼參數中傳遞的編碼

10.2在Content-Type HTTP頭中聲明的編碼。 如果這種編碼是無效的(即未知的),它將被忽略,並嘗試下一個解析機制。

10.3在響應正文中聲明的編碼。 TextResponse類不提供任何特殊的功能。 但是,HtmlResponse和XmlResponse類可以。

10.4通過查看響應主體來推斷編碼。 這是更脆弱的方法,也是最后一個嘗試。

Selector;選擇器實例化類

xpath(query)可以直接用response.xpath('//p')
css(query)可以直接用response.css('p')

class scrapy.http.HtmlResponse(url[, ...])HtmlResponse類是TextResponse的一個子類,它通過查看HTML meta http-equiv屬性來添加編碼自動發現支持,對應10.3。

class scrapy.http.XmlResponse(url[, ...])同上。

 

10.Link Extractors連接提取器

接口在scrapy.linkextractors.LinkExtractor

每個鏈接提取器唯一的公共方法是extract_links,它接收一個Response對象並返回一個scrapy.link.Link對象列表。 鏈接提取器的意圖是實例化一次,他們的extract_links方法多次調用不同的響應來提取鏈接。

鏈接提取器通過一組規則在CrawlSpider類中使用(在Scrapy中可用),但是即使您不從CrawlSpider繼承,也可以在您的蜘蛛中使用它,因為它的目的非常簡單:提取鏈接。

Class scrapy.linkextractors.lxmlhtml.LxmlLinkExtractor(allow=(), deny=(), allow_domains=(),deny_domains=(), deny_extensions=None, restrict_xpaths=(), restrict_css=(), tags=('a', 'area'), attrs=('href', ),canonicalize=False, unique=True, process_value=None, strip=True)

LxmlLinkExtractor是推薦的鏈接提取器,具有方便的過濾選項。 它使用lxml健壯的HTMLParser實現。

參數:

allow(一個正則表達式(或者列表)) - 一個正則表達式(或者正則表達式列表),為了被提取,(絕對)url必須匹配。如果沒有給(或空),它將匹配所有鏈接。

deny(正則表達式(或列表)) - (絕對)網址必須匹配才能排除(即未提取)的單個正則表達式(或正則表達式列表)。它優先於allow參數。如果沒有給(或空)它不會排除任何鏈接。

allow_domains(str或list) - 一個單獨的值或一個包含域的字符串列表,這些字段將被用於提取鏈接。

deny_domains(str或者list) - 一個單獨的值或者一個包含域的字符串列表,不會被認為是用於提取鏈接。

deny_extensions(list) - 包含擴展的單個值或字符串列表,在提取鏈接時應被忽略。如果沒有給出,它將默認為在scrapy.linkextractors包中定義的IGNORED_EXTENSIONS列表。

restrict_xpaths(str或list) - 是一個XPath(或XPath的列表),它定義了應該從中提取鏈接的響應內的區域。如果給定,只有這些XPath選擇的文本將被掃描鏈接。看下面的例子。

restrict_css(str或者list) - 一個CSS選擇器(或者選擇器列表),它定義了應該從中提取鏈接的響應內的區域。具有與restrict_xpaths相同的行為。

tags(str或list) - 提取鏈接時要考慮的標記或標記列表。默認為('a','area')

attrs(list) - 查找提取鏈接時僅考慮在tags參數中指定的標簽時應考慮的屬性或屬性列表。默認為('href',)

unique(boolean) - 是否應該對提取的鏈接應用重復過濾。

process_value(可調用) - 接收從tags和attrs中提取的每個值並且可以修改該值並返回新的值,或者返回None來忽略該鏈接的功能。如果沒有給出,process_value默認為lambda x:x。

canonicalize(Boolean) - 規范每個提取的URL(使用w3lib.url.canonicalize_url)。 默認為False。 請注意,canonicalize_url是用於重復檢查; 它可以更改服務器端可見的URL,因此對於使用規范化和原始URL的請求,響應可能會有所不同。 如果您使用LinkExtractor來跟蹤鏈接,那么保持默認的canonicalize = False更健壯。

strip(boolean) - 是否從提取的屬性中去除空白。 根據HTML5標准,必須從<a>,<area>和許多其他元素,<img>,<iframe>元素的src屬性等從href屬性中去除前導和尾隨空白,因此LinkExtractor會在默認情況下刪除空格字符。 設置strip = False將其關閉(例如,如果您從允許前/后空格的元素或屬性中提取url)。

11. Setting

Setting源文件位置:scrapy.setting,default_settings,py

11.1  為每一個爬蟲定制自己的設置選項

 

11.2  在命令行窗口下定制設置選項

 

11.3  在項目的setting.py里直接修改

11.4  訪問setting

 

11.5  通過from_crawler()函數訪問setting

 

11.6  默認的設置

AWS_ACCESS_KEY_ID:AWS訪問口令字

AWS_SECRET_ACCESS_KE:AWS訪問秘鑰

BOT_NAME:項目名稱

CONCURRENT_ITEMS:在項目處理器(也稱為Item Pipeline)中並行處理的最大並行items數(每個響應)。

CONCURRENT_REQUESTS:Scrapy下載器將執行的並發(即同時)請求的最大數量。

CONCURRENT_REQUESTS_PER_DOMAIN: 對任何單個域執行的並發(即同時)請求的最大數目。

CONCURRENT_REQUESTS_PER_IP: 對任何單個IP執行的並發(即同時)請求的最大數目。

DEFAULT_ITEM_CLASS: Default: 'scrapy.item.Item'

DEFAULT_REQUEST_HEADERS:

 

DEPTH_LIMIT: Default:0

DEPTH_PRIORITY:默認是0,正值是廣度優先爬取,負值深度優先爬取。

DEPTH_STATS:Default:True,是否收集最大的深度統計。

DEPTH_STATS_VERBOSE:默認是FALSE, 是否收集詳細深度統計信息。 如果啟用此功能,則會在統計信息中收集每個深度的請求數量。

DNSCACHE_ENABLED:Default:True是否啟用DNS內存中緩存。

DNSCACHE_SIZE:Default:10000

DNS_TIMEOUT:60s

DOWNLOADER:Default: 'scrapy.core.downloader.Downloader'

DOWNLOADER_HTTPCLIENTFACTORY:Default:'scrapy.core.downloader.webclient.ScrapyHTTPClientFactory'

DOWNLOADER_CLIENT_TLS_METHOD:Default:'TLS',使用此設置可以自定義默認HTTP / 1.1下載器使用的TLS / SSL方法。

該設置必須是以下字符串值之一:

'TLS':映射到OpenSSL的TLS_method()(又名SSLv23_method()),它允許從平台支持的最高層開始進行協議協商。 默認,推薦

'TLSv1.0':這個值強制HTTPS連接使用TLS版本1.0; 設置這個如果你想Scrapy <1.1的行為

“TLSv1.1”:強制TLS版本1.1

“TLSv1.2”:強制TLS版本1.2

“SSLv3”:強制SSL版本3(不推薦)

DOWNLOADER_MIDDLEWARES:Default:{}

DOWNLOADER_MIDDLEWARES_BASE

包含Scrapy中默認啟用的下載器中間件的字典。 低序靠近引擎,高序靠近下載器。 您不應該在您的項目中修改此設置,而是修改DOWNLOADER_MIDDLEWARES。

 

DOWNLOADER_STATS:默認值:True,是否啟用下載器統計信息收集。

 

DOWNLOAD_DELAY:默認值:0

從同一網站下載連續頁面之前,下載者應等待的時間(以秒為單位)。 這可以用來限制爬行速度,以避免打太大的服務器。 支持十進制數字。 例:

 

DOWNLOAD_DELAY = 0.25#250毫秒的延遲

此設置也受到RANDOMIZE_DOWNLOAD_DELAY設置(默認情況下啟用)的影響。 默認情況下,Scrapy不會在兩次請求之間等待一段固定時間,而是使用0.5 * DOWNLOAD_DELAY和1.5 * DOWNLOAD_DELAY之間的隨機時間間隔。

當CONCURRENT_REQUESTS_PER_IP非零時,每個IP地址而不是每個域強制執行延遲。

您也可以通過設置download_delay spider屬性來更改每個蜘蛛的此設置。

 

DOWNLOAD_HANDLERS:默認:{}

包含在您的項目中啟用的請求下載程序處理程序的字典。 例子,請參閱DOWNLOAD_HANDLERS_BASE格式。

 

DOWNLOAD_HANDLERS_BASE

 

DOWNLOAD_TIMEOUT:默認:180

下載器在超時之前等待的時間(以秒為單位)

可以使用download_timeout spider屬性和使用download_timeout Request.meta項的每個請求來為每個蜘蛛設置此超時。

DOWNLOAD_MAXSIZE:每個響應最大是下載尺寸,默認是:1073741824 (1024MB)

可以使用download_timeout spider屬性和使用download_timeout Request.meta項的每個請求來為每個蜘蛛設置此超時。

如果設為0,則表示沒有限制。

DOWNLOAD_WARNSIZE:默認:33554432(32MB)

下載器將開始發出警告的響應大小(以字節為單位)。

如果你想禁用它設置為0。

 

DOWNLOAD_FAIL_ON_DATALOSS:默認值:True.

損壞了的響應是否引發異常,即聲明的Content-Length與服務器發送的內容不匹配,或者分塊的響應沒有正確完成。 如果為True,則這些響應會引發ResponseFailed([_DataLoss])錯誤。 如果為False,則通過這些響應,並將標志數據信息添加到響應中,即:response.flags中的'dataloss'為True。

或者,可以通過使用download_fail_on_dataloss Request.meta鍵為False來設置每個請求的基礎。

在這幾種情況下,從服務器配置錯誤到網絡錯誤到數據損壞,都可能發生錯誤的響應或數據丟失錯誤。 由用戶決定是否有意義處理破壞的回應,因為他們可能包含部分或不完整的內容。 如果設置:RETRY_ENABLED為True,並且此設置設置為True,則ResponseFailed([_ DataLoss])失敗將照常重試。

 

DUPEFILTER_CLASS:默認:'scrapy.dupefilters.RFPDupeFilter',用於檢測和過濾重復請求的類。

基於請求指紋的默認(RFPDupeFilter)過濾器使用scrapy.utils.request.request_fingerprint函數。 為了改變檢查重復的方式,你可以繼承RFPDupeFilter並覆蓋它的request_fingerprint方法。 這個方法應該接受scrapy Request對象並返回它的指紋(一個字符串)。

您可以通過將DUPEFILTER_CLASS設置為“scrapy.dupefilters.BaseDupeFilter”來禁用對重復請求的過濾。 但是這樣設置可能會進入爬行循環。 在不應該被過濾的特定請求上,將dont_filter參數設置為True通常是個好主意。

 

DUPEFILTER_DEBUG:默認:False

默認情況下,RFPDupeFilter只記錄第一個重復的請求。 將DUPEFILTER_DEBUG設置為True將使其記錄所有重復的請求。

 

EDITOR:默認:vi(在Unix系統上)或IDLE編輯器(在Windows上)

編輯器用於使用編輯命令編輯蜘蛛。 此外,如果EDITOR環境變量已設置,則編輯命令將優先於默認設置

 

EXTENSIONS:默認:: {}

包含在您的項目中啟用的擴展的字典,以及他們的順序。

 

EXTENSIONS_BASE

FTP_PASSIVE_MODE:默認值:True

 

啟動FTP傳輸時是否使用被動模式。

FTP_PASSWORD:默認值:“guest”

Request meta中沒有“ftp_password”時用於FTP連接的密碼。

 

FTP_USER:默認:“anonymous” 

Request meta中沒有“ftp_user”時用於FTP連接的用戶名。

 

ITEM_PIPELINES:默認:{}

包含要使用的項目管道的字典及其順序。 順序值是任意的,但通常在0-1000范圍內定義它們。低順序的在高順序之前執行。

 

LOG_ENABLED:Default:True

LOG_ENCODING:Default:'utf-8'

 

LOG_FILE:默認:None

用於記錄輸出的文件名。 如果沒有,將使用標准(print)錯誤。

 

LOG_FORMAT:Default:'%(asctime)s [%(name)s] %(levelname)s: %(message)s'

LOG_DATEFORMAT:Default:'%Y-%m-%d %H:%M:%S'

LOG_LEVEL:Default:'DEBUG'

LOG_STDOUT:默認:False

如果為True,則所有標准輸出(和錯誤)將被重定向到日志。 例如,如果您打印“hello”,它將出現在Scrapy日志中。

 

LOG_SHORT_NAMES:默認:False

如果為True,日志將只包含根路徑。 如果設置為False,則顯示負責日志輸出的組件

 

MEMDEBUG_ENABLED:默認:False

是否啟用內存調試

 

MEMDEBUG_NOTIFY:默認:[]

當啟用內存調試時,如果此設置不為空,內存報告將被發送到指定的地址,否則報告將被寫入日志。

Example:MEMDEBUG_NOTIFY = ['user@example.com']

 

MEMUSAGE_ENABLED:默認值:True

范圍:scrapy.extensions.memusage

是否啟用內存使用擴展。 該擴展跟蹤進程使用的峰值內存(將其寫入統計信息)。 當超過內存限制(見MEMUSAGE_LIMIT_MB)時,它也可以選擇關閉Scrapy進程,並在發生這種情況時通過電子郵件通知(請參閱MEMUSAGE_NOTIFY_MAIL)。

 

MEMUSAGE_NOTIFY_MAIL:默認:False

范圍:scrapy.extensions.memusage

如果已達到內存限制,則通知電子郵件列表。

例:MEMUSAGE_NOTIFY_MAIL = ['user@example.com']

 

REDIRECT_MAX_TIMES:Default:20

REDIRECT_PRIORITY_ADJUST:默認值:+2

 

范圍:scrapy.downloadermiddlewares.redirect.RedirectMiddleware

調整相對於原始請求的重定向請求優先級:

積極的優先級調整(默認)意味着更高的優先級。

負面的優先調整意味着低優先級。

 

RETRY_PRIORITY_ADJUST:默認值:-1

范圍:scrapy.downloadermiddlewares.retry.RetryMiddleware

調整相對於原始請求的重試請求優先級:

積極的優先調整意味着更高的優先。

否定優先級調整(默認)意味着優先級較低

 

ROBOTSTXT_OBEY:默認:False

范圍:scrapy.downloadermiddlewares.robotstxt

如果啟用,Scrapy將尊重robots.txt策略。 欲了解更多信息,請參閱RobotsTxtMiddleware。

 

SCHEDULER:默認:'scrapy.core.scheduler.Scheduler'

調度程序用於抓取。

 

SCHEDULER_DEBUG:Default: False

SPIDER_MIDDLEWARES:Default:{}

 

SPIDER_MIDDLEWARES_BASE

SPIDER_MODULES:Default:[]

 

URLLENGTH_LIMIT:Default:2083

USER_AGENT:Default:"Scrapy/VERSION (+http://scrapy.org)"

 

12.Sending e-mail

http://python.usyiyi.cn/translate/scrapy_14/index.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM