




已閱讀5頁,還剩13頁未讀, 繼續(xù)免費閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
Java語言在此非常適合構(gòu)建一個“蜘蛛”程序,其內(nèi)建了對HTTP協(xié)議的支持,通過它可以傳輸大部分的網(wǎng)頁信息;其還內(nèi)建了一個HTML解析器,正是這兩個原因使Java語言成為本文構(gòu)建“蜘蛛”程序的首選。使用“蜘蛛”文章后面例1的示例程序,將會掃描一個網(wǎng)站,并尋找死鏈接。使用這個程序時需先輸入一個URL并單擊“Begin”按鈕,程序開始之后,“Begin”按鈕會變成“Cancel”按鈕。在程序掃描網(wǎng)站期間,會在“Cancel”按鈕之下顯示進度,且在檢查當前網(wǎng)頁時,也會顯示相關(guān)正常鏈接與死鏈接的數(shù)目,死鏈接將顯示在程序底部的滾動文本框中。單擊“Cancel”按鈕會停止掃描過程,之后可以輸入一個新的URL;如果期間沒有單擊“Cancel”,程序?qū)恢边\行直到查找完所有網(wǎng)頁,此后,“Cancel”按鈕會再次變回“Begin”,表示程序已停止。下面將演示示例程序是如何與可復(fù)用“Spider”類交互的,示例程序包含在例1的CheckLinks類中,這個類實現(xiàn)了ISpiderReportable接口,如例2所示,正是通過這個接口,蜘蛛類才能與示例程序相交互。在這個接口中,定義了三個方法:第一個方法是“spiderFoundURL”,它在每次程序定位一個URL時被調(diào)用,如果方法返回true,表示程序應(yīng)繼續(xù)執(zhí)行下去并找出其中的鏈接;第二個方法是“spiderURLError”,它在每次程序檢測URL導(dǎo)致錯誤時被調(diào)用(如“404 頁面未找到”);第三個方法是“spiderFoundEMail”,它在每次發(fā)現(xiàn)電子郵件地址時被調(diào)用。有了這三個方法,Spider類就能把相關(guān)信息反饋給創(chuàng)建它的程序了。在begin方法被調(diào)用后,“蜘蛛”就開始工作了;為允許程序重繪其用戶界面,“蜘蛛”是作為一個單獨的線程啟動的。點擊“Begin”按鈕會開始這個后臺線程,當后臺線程運行之后,又會調(diào)用“CheckLinks”類的run方法,而run方法是由Spider對象實例化時啟動的,如下所示:spider = new Spider(this); spider.clear(); base = new URL(url.getText(); spider.addURL(base); spider.begin(); 首先,一個新的Spider對象被實例化,在此,需要傳遞一個“ISpiderReportable”對象給Spider對象的構(gòu)造函數(shù),因為“CheckLinks”類實現(xiàn)了“ISpiderReportable”接口,只需簡單地把它作為當前對象(可由關(guān)鍵字this表示)傳遞給構(gòu)造函數(shù)即可;其次,在程序中維護了一個其訪問過的URL列表,而“clear”方法的調(diào)用則是為了確保程序開始時URL列表為空,程序開始運行之前必須添加一個URL到它的待處理列表中,此時用戶輸入的URL則是添加到列表中的第一個,程序就由掃描這個網(wǎng)頁開始,并找到與這個起始URL相鏈接的其他頁面;最后,調(diào)用“begin”方法開始運行“蜘蛛”,這個方法直到“蜘蛛”工作完畢或用戶取消才會返回。當“蜘蛛”運行時,可以調(diào)用由“ISpiderReportable”接口實現(xiàn)的三個方法來報告程序當前狀態(tài),程序的大部分工作都是由“spiderFoundURL”方法來完成的,當“蜘蛛”發(fā)現(xiàn)一個新的URL時,它首先檢查其是否有效,如果這個URL導(dǎo)致一個錯誤,就會把它當作一個死鏈接;如果鏈接有效,就會繼續(xù)檢查它是否在一個不同的服務(wù)器上,如果鏈接在同一服務(wù)器上,“spiderFoundURL”返回true,表示“蜘蛛”應(yīng)繼續(xù)跟蹤這個URL并找出其他鏈接,如果鏈接在另外的服務(wù)器上,就不會掃描是否還有其他鏈接,因為這會導(dǎo)致“蜘蛛”不斷地瀏覽Internet,尋找更多、更多的網(wǎng)站,所以,示例程序只會查找用戶指定網(wǎng)站上的鏈接。構(gòu)造Spider類前面已經(jīng)講了如何使用Spider類,請看例3中的代碼。使用Spider類及“ISpiderReportable”接口能方便地為某一程序添加“蜘蛛”功能,下面繼續(xù)講解Spider類是怎樣工作的。Spider類必須保持對其訪問過的URL的跟蹤,這樣做的目的是為了確?!爸┲搿辈粫L問同一URL一次以上;進一步來說,“蜘蛛”必須把URL分成三組,第一組存儲在“workloadWaiting”屬性中,包含了一個未處理的URL列表,“蜘蛛”要訪問的第一個URL也存在其中;第二組存儲在“workloadProcessed”中,它是“蜘蛛”已經(jīng)處理過且無需再次訪問的URL;第三組存儲在“workloadError”中,包含了發(fā)生錯誤的URL。Begin方法包含了Spider類的主循環(huán),其一直重復(fù)遍歷“workloadWaiting”,并處理其中的每一個頁面,當然我們也想到了,在這些頁面被處理時,很可能有其他的URL添加到“workloadWaiting”中,所以,begin方法一直繼續(xù)此過程,直到調(diào)用Spider類的cancel方法,或“workloadWaiting”中已不再剩有URL。這個過程如下:cancel = false; while ( !getWorkloadWaiting().isEmpty() & !cancel ) Object list = getWorkloadWaiting().toArray(); for ( int i=0; (iLIST.LENGTH)&!CANCEL; )processURL(URL)listi); 當上述代碼遍歷“workloadWaiting”時,它把每個需處理的URL都傳遞給“processURL”方法,而這個方法才是真正讀取并解析URL中HTML信息的。讀取并解析HTMLJava同時支持訪問URL內(nèi)容及解析HTML,而這正是“processURL”方法要做的。在Java中讀取URL內(nèi)容相對還比較簡單,下面就是“processURL”方法實現(xiàn)此功能的代碼:URLConnection connection = url.openConnection(); if ( (connection.getContentType()!=null) &!connection.getContentType().toLowerCase().startsWith(text/) ) getWorkloadWaiting().remove(url); getWorkloadProcessed().add(url); log(Not processing because content type is: +connection.getContentType() ); return; 首先,為每個傳遞進來的變量url中存儲的URL構(gòu)造一個“URLConnection”對象,因為網(wǎng)站上會有多種類型的文檔,而“蜘蛛”只對那些包含HTML,尤其是基于文本的文檔感興趣。前述代碼是為了確保文檔內(nèi)容以“text/”打頭,如果文檔類型為非文本,會從等待區(qū)移除此URL,并把它添加到已處理區(qū),這也是為了保證不會再次訪問此URL。在對特定URL建立連接之后,接下來就要解析其內(nèi)容了。下面的代碼打開了URL連接,并讀取內(nèi)容:InputStream is = connection.getInputStream(); Reader r = new InputStreamReader(is); 現(xiàn)在,我們有了一個Reader對象,可以用它來讀取此URL的內(nèi)容,對本文中的“蜘蛛”來說,只需簡單地把其內(nèi)容傳遞給HTML解析器就可以了。本例中使用的HTML解析器為Swing HTML解析器,其由Java內(nèi)置,但由于Java對HTML解析的支持力度不夠,所以必須重載一個類來實現(xiàn)對HTML解析器的訪問,這就是為什么我們要調(diào)用“HTMLEditorKit”類中的“getParser”方法。但不幸的是,Sun公司把這個方法置為protected,唯一的解決辦法就是創(chuàng)建自己的類并重載“getParser”方法,并把它置為public,這由“HTMLParse”類來實現(xiàn),請看例4:import javax.swing.text.html.*; public class HTMLParse extends HTMLEditorKit public HTMLEditorKit.Parser getParser()return super.getParser(); 這個類用在Spider類的“processURL”方法中,我們也會看到,Reader對象會用于讀取傳遞到“HTMLEditorKit.Parser”中網(wǎng)頁的內(nèi)容:HTMLEditorKit.Parser parse = new HTMLParse().getParser(); parse.parse(r,new Parser(url),true); 請留意,這里又構(gòu)造了一個新的Parser類,這個Parser類是一個Spider類中的內(nèi)嵌類,而且還是一個回調(diào)類,它包含了對應(yīng)于每種HTML tag將要調(diào)用的特定方法。在本文中,我們只需關(guān)心兩類回調(diào)函數(shù),它們分別對應(yīng)一個簡單tag(即不帶結(jié)束tag的tag,如)和一個開始tag,這兩類回調(diào)函數(shù)名為“handleSimpleTag”和“handleStartTag”。因為每種的處理過程都是一樣的,所以“handleStartTag”方法僅是簡單地調(diào)用“handleSimpleTag”,而“handleSimpleTag”則會負責(zé)從文檔中取出超鏈接,這些超鏈接將會用于定位“蜘蛛”要訪問的其他頁面。在當前tag被解析時,“handleSimpleTag”會檢查是否存在一個“href”或超文本引用:String href = (String)a.getAttribute(HTML.Attribute.HREF); if( (href=null) & (t=HTML.Tag.FRAME) )href = (String)a.getAttribute(HTML.Attribute.SRC); if ( href=null )return; 如果不存在“href”屬性,會繼續(xù)檢查當前tag是否為一個Frame,F(xiàn)rame會使用一個“src”屬性指向其他頁面,一個典型的超鏈接通常為以下形式:Click Here上面鏈接中的“href”屬性指向其鏈接到的頁面,但是“l(fā)inkedpage.html”不是一個地址,它只是指定了這個Web服務(wù)器上一個頁面上的某處,這稱為相對URL,相對URL必須被解析為絕對URL,而這由以下代碼完成:URL url = new URL(base,str); 這又會構(gòu)造一個URL,str為相對URL,base為這個URL上的頁面,這種形式的URL類構(gòu)造函數(shù)可構(gòu)造一個絕對URL。在URL變?yōu)檎_的絕對形式之后,通過檢查它是否在等待區(qū),來確認此URL是否已經(jīng)被處理過。如果此URL沒有被處理過,它會添加到等待區(qū),之后,它會像其他URL一樣被處理。例1:查找死鏈接(ChcekLinks.java)import java.awt.*; import javax.swing.*; import .*; import java.io.*; public class CheckLinks extends javax.swing.JFrame implementsRunnable,ISpiderReportable public CheckLinks()/INIT_CONTROLSsetTitle(找到死鏈接); getContentPane().setLayout(null); setSize(405,288); setVisible(false); label1.setText(輸入一個URL:); getContentPane().add(label1); label1.setBounds(12,12,84,12); begin.setText(Begin); begin.setActionCommand(Begin); getContentPane().add(begin); begin.setBounds(12,36,84,24); getContentPane().add(url); url.setBounds(108,36,288,24); errorScroll.setAutoscrolls(true); errorScroll.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); errorScroll.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); errorScroll.setOpaque(true); getContentPane().add(errorScroll); errorScroll.setBounds(12,120,384,156); errors.setEditable(false); errorScroll.getViewport().add(errors); errors.setBounds(0,0,366,138); current.setText(當前處理進度:); getContentPane().add(current); current.setBounds(12,72,384,12); goodLinksLabel.setText(正常鏈接:0); getContentPane().add(goodLinksLabel); goodLinksLabel.setBounds(12,96,192,12); badLinksLabel.setText(死鏈接:0); getContentPane().add(badLinksLabel); badLinksLabel.setBounds(216,96,96,12); /INIT_MENUS/REGISTER_LISTENERSSymAction lSymAction = new SymAction(); begin.addActionListener(lSymAction); /*參數(shù)args未使用*/static public void main(String args)(new CheckLinks().setVisible(true); /*添加通知*/public void addNotify()/記錄窗口尺寸并調(diào)用父類的addNotify.Dimension size = getSize(); super.addNotify(); if ( frameSizeAdjusted )return; frameSizeAdjusted = true; /根據(jù)菜單欄等調(diào)整Frame尺寸Insets insets = getInsets(); javax.swing.JMenuBar menuBar = getRootPane().getJMenuBar(); int menuBarHeight = 0; if ( menuBar != null )menuBarHeight = menuBar.getPreferredSize().height; setSize(insets.left + insets.right + size.width, insets.top +insets.bottom + size.height + menuBarHeight); boolean frameSizeAdjusted = false; /DECLARE_CONTROLSjavax.swing.JLabel label1 = new javax.swing.JLabel(); javax.swing.JButton begin = new javax.swing.JButton(); javax.swing.JTextField url = new javax.swing.JTextField(); javax.swing.JScrollPane errorScroll =new javax.swing.JScrollPane(); /*存儲錯誤信息*/javax.swing.JTextArea errors = new javax.swing.JTextArea(); javax.swing.JLabel current = new javax.swing.JLabel(); javax.swing.JLabel goodLinksLabel = new javax.swing.JLabel(); javax.swing.JLabel badLinksLabel = new javax.swing.JLabel(); /DECLARE_MENUS/*后臺蜘蛛線程*/protected Thread backgroundThread; protected Spider spider; protected URL base; protected int badLinksCount = 0; protected int goodLinksCount = 0; /*用于分發(fā)事件的內(nèi)部類*/class SymAction implements java.awt.event.ActionListener public void actionPerformed(java.awt.event.ActionEvent event)Object object = event.getSource(); if ( object = begin )begin_actionPerformed(event); /*當begin或cancel按鈕被點擊時調(diào)用* *參數(shù)event與按鈕相連*/void begin_actionPerformed(java.awt.event.ActionEvent event)if ( backgroundThread=null ) begin.setLabel(Cancel); backgroundThread = new Thread(this); backgroundThread.start(); goodLinksCount=0; badLinksCount=0; else spider.cancel(); /*執(zhí)行后臺線程操作*/public void run()try errors.setText(); spider = new Spider(this); spider.clear(); base = new URL(url.getText(); spider.addURL(base); spider.begin(); Runnable doLater = new Runnable()public void run()begin.setText(Begin); ; SwingUtilities.invokeLater(doLater); backgroundThread=null; catch ( MalformedURLException e ) UpdateErrors err = new UpdateErrors(); err.msg = 錯誤地址。; SwingUtilities.invokeLater(err); /*當找到某一URL時由蜘蛛調(diào)用,在此驗證鏈接。* *參數(shù)base是找到鏈接時的頁面*參數(shù)url是鏈接地址*/public boolean spiderFoundURL(URL base,URL url)UpdateCurrentStats cs = new UpdateCurrentStats(); cs.msg = url.toString(); SwingUtilities.invokeLater(cs); if ( !checkLink(url) ) UpdateErrors err = new UpdateErrors(); err.msg = url+(on page + base + ); SwingUtilities.invokeLater(err); badLinksCount+; return false; goodLinksCount+; if ( !url.getHost().equalsIgnoreCase(base.getHost() )return false; elsereturn true; /*當發(fā)現(xiàn)URL錯誤時調(diào)用* *參數(shù)url是導(dǎo)致錯誤的URL*/public void spiderURLError(URL url)/*由內(nèi)部調(diào)用檢查鏈接是否有效* *參數(shù)url是被檢查的鏈接*返回True表示鏈接正常有效*/protected boolean checkLink(URL url)try URLConnection connection = url.openConnection(); connection.connect(); return true; catch ( IOException e ) return false; /*當蜘蛛找到電子郵件地址時調(diào)用*參數(shù)email為找到的電子郵件地址*/public void spiderFoundEMail(String email)/*以線程安全方式更新錯誤信息的內(nèi)部類*/class UpdateErrors implements Runnable public String msg; public void run()errors.append(msg); /*以線程安全方式更新當前狀態(tài)信息*/class UpdateCurrentStats implements Runnable public String msg; public void run()current.setText(當前進度: + msg ); goodLinksLabel.setText(正常鏈接: + goodLinksCount); badLinksLabel.setText(死鏈接: + badLinksCount); 例2:報告蜘蛛事件(ISpiderReportable.java)import .*; interface ISpiderReportable public boolean spiderFoundURL(URL base,URL url); public void spiderURLError(URL url); public void spiderFoundEMail(String email); 例3:可復(fù)用的蜘蛛類(Spider.java)import java.util.*; import .*; import java.io.*; import javax.swing.text.*; import javax.swing.text.html.*; public class Spider /*導(dǎo)致錯誤的URL集合*/protected Collection workloadError = new ArrayList(3); /*等待區(qū)URL集合*/protected Collection workloadWaiting = new ArrayList(3); /*處理過的URL集合*/protected Collection workloadProcessed = new ArrayList(3); protected ISpiderReportable report; /*表明處理過程是否應(yīng)取消的標志*/protected boolean cancel = false; /*構(gòu)造函數(shù)*參數(shù)report為實現(xiàn)了ISpiderReportable接口的類*/public Spider(ISpiderReportable report)this.report = report; /*獲取導(dǎo)致錯誤的URL*/public Collection getWorkloadError()return workloadError; /*獲取在等待的URL*應(yīng)添加至少一個URL到此集合以啟動蜘蛛*/public Collection getWorkloadWaiting()return workloadWaiting; /*獲取被處理過的URL*/public Collection getWorkloadProcessed()return workloadProcessed; /*清空所有*/public void clear()getWorkloadError().clear(); getWorkloadWaiting().clear(); getWorkloadProcessed().clear(); /*設(shè)置一標志,使begin方法在完成之前返回*/public void cancel()cancel = true; public void addURL(URL url)if ( getWorkloadWaiting().contains(url) )return; if ( getWorkloadError().contains(url) )return; if ( getWorkloadProcessed().contains(url) )return; log(正添加到工作區(qū): + url ); getWorkloadWaiting().add(url); public void processURL(URL url)try log(正在處理: + url ); /獲取URL的內(nèi)容URLConnection connection = url.openConnection(); if ( (connection.getContentType()!=null) &!connection.getContentType().toLowerCase().startsWith(text/) ) getWorkloadWaiting().remove(url); getWorkloadProcessed().add(url); log(不會進行正理,因為類型為: +connection.getContentType() ); return; /讀取URLInputStream is = connection.getInputStream(); Reader r = new InputStreamReader(is); /解析URLHTMLEditorKit.Parser parse = new HTMLParse().getParser(); parse.parse(r,new Parser(url),true); catch ( IOException e ) getWorkloadWaiting().remove(url); getWorkloadError().add(url); log(錯誤: + url ); report.spiderURLError(url); return; /標記此URL已完成getWorkloadWaiting().remove(url); getWorkloadProcessed().add(url); log(已完成: + url ); public void begin()cancel = false; while ( !getWorkloadWaiting().isEmpty() & !cancel ) Object list = getWorkloadWaiting().toArray(); for ( int i=0; (iLIST.LENGTH)&!CANCEL; )processURL(URL)listi); /*HTML解析器回調(diào)函數(shù)*/protected class Parserextends HTMLEditorKit.ParserCallback protected URL base; public Parser(URL base)this.base = base; public void handleSimpleTag(HTML.Tag t,MutableAttributeSet a,int pos)String href = (String)a.getAttribute(HTML.Attribute.HREF); if( (href=null) & (t=HTML.Tag.FRAME) )href = (String)a.getAttribute(HTML.Attribute.SRC); if ( href=null )return; int i = href.indexOf(#); if ( i!=-1 )href = href.substring(0,i); if ( href.toLowerCase().startsWith(mailto:) ) report.spiderFoundEMail(href); return; handleLink(base,href); public void handleStartTag(HTML.Tag t,MutableAttributeSet a,int pos)handleSimpleTag(t,a,pos); /以同樣的方式處理protected void handleLink(URL base,String str)try URL url = new URL(base,str); if ( report.spiderFoundURL(base,url) )addURL(url); catch ( MalformedURLException e ) log(找到畸形URL: + str ); /*由內(nèi)部調(diào)用來記錄信息*僅是把日志寫到標準輸出* *參數(shù)entry為寫到日志的信息*/public void log(String entry)System.out.println( (new Date() + : + entry ); 例4:解析HTML(HTMLParse.java)import javax.swing.text.html.*; public class HTMLParse extends HTMLEditorKit public HTMLEditorKit.Parser getParser()return super.getParser(); 在Eclipse中構(gòu)建Heritrix 這里采用的是Heritrix 1.14.4(2010年5月10日的版本 目前來看是最新版本) 1.首先從/projects/archive-crawler/ 中下載 heritrix-1.14.4.zip heritrix-1.14.4-src.zip 2.在Eclipse 中創(chuàng)建一個java project的工程,分別對 heritrix-1.14.4.zip heritrix-1.14.4-src.zip 進行解壓。 3.將heritrix-1.14.4-src.zip解壓中的src/java 中的 com、org、st三個文件夾復(fù)制到工程src下。 4.將heritrix-1.14.4-src.zip解壓中src中conf文件夾復(fù)制到項目根目錄。 5.將heritrix-1.14.4-src.zip解壓中l(wèi)ib文件夾復(fù)制到項目根目錄。 6.將heritrix-1.14.4-src.zip解壓中src/resources/org/archive/util中tlds-alpha-by-domain.txt文件復(fù)制到工程中org.archive.util包下。 7.將heritrix-1.14.4.zip解壓中webapps文件夾復(fù)制到項目根目錄。 如果文件夾名稱不是webapps 需要在Heritrix.java中進行相應(yīng)的更改。 Java代碼 1. /* 2. *throwsIOException 3. *returnReturnsthedirectoryunderwhichresidetheWARfiles 4. *weretoloadintotheservletcontainer. 5. */ 6. publicstaticFilegetWarsdir()
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025美甲師高級考試試卷:美甲行業(yè)創(chuàng)新發(fā)展策略與市場分析
- 2025年征信國際合作案例分析試題集
- 2025計算機輔助設(shè)計師考試UIUX設(shè)計實戰(zhàn)試卷
- 2025年電梯司機(二十二級)職業(yè)技能鑒定模擬試卷
- 2025年教師招聘考試政治學(xué)科專業(yè)知識試卷答案與難點解析(政治)
- 農(nóng)業(yè)科技與農(nóng)業(yè)機械化應(yīng)用知識要點
- 愛心接力一次感動人心的故事記事11篇范文
- 汽車與交通設(shè)備行業(yè)智能化駕駛系統(tǒng)市場分析報告
- 農(nóng)產(chǎn)品供應(yīng)鏈管理案例分析題
- 2025年K2教育STEM課程實施對學(xué)生跨學(xué)科學(xué)習(xí)能力培養(yǎng)的長期效果評估
- 公司與旅行社合作合同范本
- 五年級上冊語文預(yù)習(xí)晨讀晚默小紙條
- 血液體液濺灑處理
- 電商平臺商家入駐協(xié)議書
- 學(xué)生宿舍管理服務(wù)方案
- 宣傳錄音制作合同范本
- 分式與分式方程壓軸題(5個類型50題)-【??級狠S題】2023-2024學(xué)年八年級數(shù)學(xué)下冊壓軸題攻略(解析版)
- 《安全隱患排查整改》主題班會
- 全國公共數(shù)據(jù)運營年度發(fā)展報告
- 天津市部分區(qū)2023-2024學(xué)年高一下學(xué)期期末考試語文試題(解析版)
- 貴州省黔西南州2023-2024學(xué)年英語八下期末教學(xué)質(zhì)量檢測試題含答案
評論
0/150
提交評論