#34;VBA信息獲取與處理"教程中第八個專題"VBA與HTML文檔"的第七節"HTML DOM的對象事件及關聯"太枯燥了,希望想掌握這方面知識的朋友能參考我的教程學習。我們今天 開始第九個專題的學習"利用IE抓取網絡數據"。
我們的網抓部分在講解了XMLHTTP方法后,利用兩個專題的進度進行了一些和VBA關系不是很大的有關網絡知識的講解,這兩個專題對于我們重新認識網抓數據有著非常重要的意義,雖然我的講解還不能面面俱到,但對于我經常倡導的VBA定位來說,是足夠的,再者,學習是個不斷積累前進的過程,要掌握的是一些基本的理論,然后把這些應用到自己的實際中去,這才是關鍵。從這個專題開始我們繼續網抓的學習。這個專題是利用IE抓取網絡數據。其實就是利用控件來完成我們的工作。
為了獲取網頁的數據,我們可以通過創建IE控件或webbrowser控件,結合htmlfile對象的方法和屬性,模擬瀏覽器操作,獲取瀏覽器頁面的數據。
這種方法可以模擬大部分的瀏覽器操作。瀏覽器能看到的數據就能用代碼獲取,但是有個致命的缺點:除去各種彈窗相當煩人外,兼容性也確實是個很傷腦筋的問題。在我自己的實踐中感覺這種方法不是很穩定(僅僅是感覺)。
我們在實際工作中遇到網站和網頁相關問題,例如:如何下載網頁數據?網頁之間的通訊是怎么實現的、它們能不能被控制等等。如果你是用VB/VBA/腳本或其它支持自動化對象(AUTOMATION)的語言編程,有一個值得了解的方法是掌握對象模型:將網頁視為對象來控制,這個方法需要了解的是IE的自動化對象(InternetExplorer.Application)或IE控件(Microsoft Internet Controls),以及標準的文檔對象模型(Document)。相關的知識我在前兩個專題中做了大量的講解,這里就不再詳細的說明了。
我給出下面的代碼:
Set ie = CreateObject("InternetExplorer.Application") '創建對象
ie.Visible = True '使IE頁面可見,做完這一步,在VBA之外可以看到一個新的IE
ie.navigate "about:blank" '建立一個空白頁
上面這幾行代碼的作用是創建一個IE應用程序對象,并打開一個空白的網頁。這個網頁獨立于VBA的應用程序(WORD或EXCEL)之外,事實上,你必須自已關掉它,或者用ie.Quit下令退出——注意一下,單純的關閉VBA或SET ie=nothing是不會退出這個網頁的。我們經常用的是將第3行的字符串替換成一個網站的名字,或者替換成一個你主機中的文檔名,也可以是一個圖片名,都是可以的。和你在IE地址欄輸入名稱瀏覽這些文檔是一樣效果。
如果僅僅是創建了一個空的模型是沒有任何利用的價值的,我們需要真正的網頁,這時就需要我們在VBA的應用程序外打開一個完整的網頁了,直到網頁完全加載我們的操作才能向下進行。
我們修正一下上面的那段打開空網頁的代碼:
Sub mynz()
Set ie = CreateObject("InternetExplorer.Application") '創建對象
ie.Visible = True '使IE頁面可見,做完這一步,在VBA之外可以看到一個新的IE
ie.navigate " https://baijiahao.baidu.com" '建立一個空白頁
Do Until .ReadyState = 4 '檢查網頁是否加載完畢(4表示完全加載)
DoEvents '循環中交回工作權限給系統,以免"軟死機"
Loop
End sub
在上面的代碼中增加了幾行:
Do Until .ReadyState = 4 '檢查網頁是否加載完畢(4表示完全加載)
DoEvents '循環中交回工作權限給系統,以免"軟死機"
Loop
這幾行代碼可以保證網頁的加載完成,這是根據ie.ReadyState的返回值來判斷的。
readyState一共有5中狀態:
狀態 含義 說明
0 未初始化 對象已建立,但是尚未初始化(尚未調用open方法)
1 初始化 對象已建立,尚未調用send方法
2 發送數據 send()方法已調用,但是當前的狀態及http頭未知
3 數據傳送中 已接收部分數據,因為響應及http頭不全,這時通過responseBody和responseText獲取部分數據會出現錯誤
4 數據接收完畢 此時可以通過通過responseBody和responseText獲取完整的回應數據
通過以上的分析,我們可以看出,只用當.ReadyState = 4時網頁的數據才是有效的數據。
當網頁加載完畢,剩下的工作就是從網頁中抓取數據了,數據的抓取主要是利用控件對象的屬性和方法。
1)用Set doc = ie.Document 取得網頁的文檔對象
從文檔對象(Document)以下展開的對象模型,它代表網頁的內容,和前面那個IE的應用程序不是同一個體系.
Documnet(文檔)是文檔對象模型,相當于OFFICE對象中的APPLICATION,取得Document之后,不論修改網頁還是讀寫網頁,還是觸發事件,一切都好說,每個URL都對應有一個Documnet(這是假如定成功導航Navigate到那個URL完成,因此之前要求確定IE對象READSTATE,以確定對應URL的Document打開了)
2) 在Documnet之下可以取得documentElement和body兩個節點。
可以用下面的語句:
set xbody=doc.Body '取得body對象
set xDoc=doc. documentElement '取得根節點
body前面已經說過,相當于標記的對象,根節點相當于網頁中的標記元素的對象,MHTML的類型庫定義里,它們都屬于HTMLHtmlElement類型的對象,下面我把這種類型的對象稱為一個"節點",不過要注意的是文檔對象不是節點對象,它是HTMLDocument類型。根節點和body節點不同的是根節點包括整個網頁,在HTML的文檔對象模型中,這類對象有幾種屬性可以取得其中的內容:
對象.innerHtml '對象內部的HTML文本
對象.OuterHtml '對象中的HTML文本,包括對象本身的HTML標記在內
對象.innerText '對象內部的TEXT,不包括HTML標記
對象.OuterText '同上,包括對象本身的文本
所以,如果我們要抓取某個網站的所有HTML內容,代碼可以這樣寫:
set doc=ie.Document
set xDoc=doc. documentElement '取得根節點
strX=xDoc.OuterHtml '取得所有的HTML內容
3) 每一個標記節點對象之下都有一個名為ChildNodes的集合,它包含了"直屬于本節點下的標記",就象是文件目錄,根目錄下的子目錄.
我們可以看到:HTML標記是文檔的根節點,是Document的Childnodes集合中的一個成員(Document不是節點,是另一種類型對象,上一級文檔,但它可以有下級節點集合,正如磁盤可以有下級目錄,但它本身不是目錄),BODY是根節點的ChildNodes集合中的一個成員,而DIV和P兩個節點則是BODY的ChildNodes集合中的兩個成員,同樣也有自已的Childnoes集合。
我們要注意:文檔對象模型中,集合與OFFICE的集合有所不同,集合是從0開始計數的,計數屬性是Length而不是Count。
4)除了ChildNodes集合,大家在網頁文檔對象中還常見到的就是很大氣的一種集合:All集合,這是"最糊涂"的一種集合,文檔和各級節點都帶有這個集合,正如這個名字所示,它是不分層次的,但用起來也很方便:
Set doc=ie.Document
Set xCols=doc.All '取得文檔中的所有節點集合
Set xbCols=doc.body.All '取得body節點下所有的節點集合
雖然任何標記節點都有ALL集合,但我們還是喜歡用DOCUMENT的ALL,原因無它,文檔最大,一鍋燴的ALL找起來也最合適。ALL查找是有條件的:如果這個標記沒有ID,你無法查到它的名字。
不過,ALL集合有一個很方便的特性:ID可以掛到ALL集合之下:
strX=doc.All.mytag.innerhtml
5)獲得文檔對象的getElementsByName集合,可以利用下面的方法:
set mydivs=doc. getElementsByName("div") '取得所有DIV標記,注意還是集合
6) 文檔對象的FORMS集合,因為大部分網頁的數據提交都是通過FORM標記提交的:
Set myForms=doc.Forms '取得所有的FORM標記
Set frmX=myForms.item(0) '第1個FORM
FORM標記節點代表的對象是很多朋友關心的內容——在網頁對象中,它可以發送數據到服務器,使服務器刷新網頁(實際上是服務器按某個格式約定發回數據),我們可以把網頁的FORM看成是一個遠程的函數調用接口,FORM標記中的ACTION指向的URL地址就是函數入口,而FORM標記內的各個INPUT標記節點就是函數的參數,當發出FORM.Submit方法時,就是遠程調用函數了,在服務器端,諸如ASP,PHP就是老老實實找FORM的參數,不管你是用GET還是POST:
frmX.submit '相當于用戶在頁面上按下FORM的發送按鍵
上面我羅列了獲取網頁數據的一般的方法,并沒有什么特別的使用要求,大家可以根據自己的習慣來利用,這個專題之后的內容就是靈活運用這些知識點來解決實際問題了。
本節知識點回向:
如何提交表單?如何下載圖片的地址?如何獲得表的數據?
在我的系列書籍中一直在強調"搭積木"的編程思路,這也是學習利用VBA的主要方法,特別是職場人員,更是要采用這種方案。其主要的內涵:
1 代碼不要自己全部的錄入。你要做的是把積木放在合適的位置然后去修正代碼,一定要拷貝,從你的積木庫中去拷貝,然后修正代碼,把時間利用到高效的思考上。
2 建立自己的"積木庫"。平時在學習過程中,把自己認為有用的代碼放在一起,多積累,在用到的時候,可以隨時拿來。你的積木庫資料越多,你做程序的思路就會越廣。
VBA是利用Office實現個人小型辦公自動化的有效手段(工具)。這是我對VBA的應用界定。在取代OFFICE新的辦公軟件沒有到來之前,誰能在數據處理方面做到極致,誰就是王者。其中登峰至極的技能非VBA莫屬!
我記得20年前自己初學VBA時,那時的資料甚少,只能看源碼自己琢磨,真的很難。20年過去了,為了不讓學習VBA的朋友重復我之前的經歷,我根據自己多年VBA實際利用經驗,推出了六部VBA專門教程:
第一套:VBA代碼解決方案 是VBA中各個知識點的講解,教程共147講,覆蓋絕大多數的VBA知識點,初學必備;
第二套:VBA數據庫解決方案 數據庫是數據處理的專業利器,教程中詳細介紹了利用ADO連接ACCDB和EXCEL的方法和實例操作,適合中級人員的學習。
第三套:VBA數組與字典解決方案 數組和字典是VBA的精華,字典是VBA代碼水平提高的有效手段,值得深入的學習,是初級及中級人員代碼精進的手段。
第四套:VBA代碼解決方案之視頻 是專門面向初學者的視頻講解,可以快速入門,更快的掌握這門技能。這套教程是第一套教程的視頻講解,聽元音更易接受。
第五套:VBA中類的解讀和利用 這是一部高級教程,講解類的虛無與肉身的度化,類的利用雖然較少,但仔細的學習可以促進自己VBA理論的提高。這套教程的領會主要是讀者的領悟了,領悟一種佛學的哲理。
第六套教程:《VBA信息獲取與處理》,這是一部高級教程,涉及范圍更廣,實用性更強,面向中高級人員。教程共二十個專題,包括:跨應用程序信息獲得、隨機信息的利用、電子郵件的發送、VBA互聯網數據抓取、VBA延時操作,剪切板應用、Split函數擴展、工作表信息與其他應用交互,FSO對象的利用、工作表及文件夾信息的獲取、圖形信息的獲取以及定制工作表信息函數等等內容。
大家可以根據以上資料1→3→2→6→5或者是4→3→2→6→5的順序逐漸深入的逐漸學習。教程提供講解的同時提供了大量的積木,如需要可以WeChat: NZ9668
如太白詩云:眾鳥高飛盡,孤云獨去閑。相看兩不厭,只有敬亭山。學習的過程也是修心的過程,修一個平靜的心。在代碼的世界中,心平靜了,心情好了,身體自然而然就好。心靜則正,內心里沒有那么多邪知邪見,也就沒有那么多妄想。利人就是利己。這些教程也是為幫助大家起航,助上我自己之力,我的上述教程是我多的經驗的傳遞,
"水善利萬物而不爭",綿綿密密,微則無聲,巨則洶涌。學習亦如此,知道什么是自己所需要的,不要蜷縮在一小塊自認為天堂的世界里,待到暮年時再去做自欺欺人的言論。要努力提高自己,用一顆充滿生機的心靈,把握現在,這才是進取。越是有意義的事情,困難會越多。愿力決定始終,智慧決定成敗。不管遇到什么,都是風景。看淡紛爭,看輕得失。茶,滿也好,少也好,不要計較;濃也好,淡也好,其中自有值得品的味道。去感悟真實的時間,靜下心,多學習,積累福報。而不是天天混日子,也不是天天熬日子。在后疫情更加嚴峻的存量殘殺世界中,為自己的生存進行知識的儲備,特別是新知識的儲備。學習時微而無聲,利用時則巨則洶涌。
每一分收獲都是成長的記錄,怎無憑,正是這種執著,成就了朝霞的燦爛。最后將一闕詞送給致力于VBA學習的朋友,讓大家感受一下學習過程的枯燥與執著:
浮云掠過,暗語無聲,
唯有清風,驚了夢中啼鶯。
望星,疏移北斗,
奈將往事雁同行。
阡陌人,昏燈明暗,
忍顧長亭。
多少VBA人,
暗夜中,悄聲尋夢,盼卻天明。
怎無憑!
回向學習利用VBA的歷歷往事,不勝感慨,謹以這些文字給大家,分享我多年工作實際經驗的成果,隨喜這些有用的東西,給確實需要利用VBA的同路人。
分享成果,隨喜正能量
索引擎和聚合類新聞App之所以有源源不斷的新內容供予用戶瀏覽,原因就在于有網絡爬蟲技術的加持。網絡爬蟲的應用對于用戶來說,是一大福利——我們可以從一個搜索引擎輕松搜索到各個領域的信息。但是,對于原創方來說,就涉及到版權被侵犯的問題了。工具理性,但不意味著操持工具的人就可以假借“工具理性”肆意侵犯他人的合法權益,網絡爬蟲技術的應用還應該要在法理之內。
工作的時候,想要查找“產品設計”,可以直接在搜索引擎上輸入內容,就可以直接找到數以百萬計的資料。
上下班路上,刷新聞類APP的時候,只要愿意,就會有源源不斷的新的信息,足夠刷一路的時間。
搜索引擎和(大多數)新聞類APP都不自己生產內容(雖然有些平臺孵化了自己的內容,但也只占整個平臺內容的很少的一部分,更重要的是,成本非常高)。
那么,他們的大量的內容從哪里來?
“我們不生產內容,只是內容的搬運工”,將互聯網上的內容“搬運”到自己的服務器上,這就是爬蟲。
首先,我們需要了解一下互聯網的結構。
互聯網上的內容數以億計,雖然很復雜,但說白了就是一張大網,網上的每個節點就是一個網頁,連接網頁的超鏈接(Hyperlinks)相當于線,線把所有的節點連接在一起,形成了一個復雜的網。
通過點擊超鏈接的文字或者圖片,就可以跳轉到對應的網頁。爬蟲可以自動訪問到每一個網頁,并把網頁的內容保存下來。
世界上第一個網絡爬蟲由麻省理工學院的學生馬修·格雷(Matthew Gray)在1993年寫成,之后的爬蟲盡管越來越復雜。
比如:可以實現更快的訪問速度、訪問更多的網頁、更好的將網站內容解析出來。但爬蟲的基本原理是一樣的,都主要包括三個部分:訪問網頁鏈接,下載網頁內容,解析網頁內容。
爬蟲的工作過程與我們查找網頁的過程是一樣的。
比如,我們想要查一下豆瓣上最新的電影:首先,在瀏覽器地址欄輸入網址鏈接https://movie.douban.com/,之后,瀏覽器會跳轉到豆瓣電影。最后,我們就可以找到當前熱映的電影。
同樣的,一個最簡單的爬蟲三步就可以爬取一個網頁——首先,訪問這個網頁,之后,把網頁內容下載下來,最后,對下載的內容進行解析。
最簡單的爬蟲三步就可以爬取一個網頁,那么要寫多少行代碼呢?
我們寫一個爬蟲,爬取豆瓣的“一周口碑榜”,只要7行代碼!
這里我們使用Python語言,至于為什么選擇Python語言,會在后面交代清楚,如果不懂Python也沒有關系,了解爬蟲是如何工作的就可以了。
代碼如下:
import requests from lxml
import html url=’https://movie.douban.com/’ # 1、需要爬數據的網址
page=requests.Session.get(url) # 2、訪問網頁
tree=html.fromstring(page.text) # 3、解析網頁的過程
result=tree.xpath(‘//td[@class=”title”]//a/text’) #3、解析網頁的過程
print(result) # 打印出結果
在Python環境中運行這幾行代碼,就可以獲取“一周口碑榜”了,結果如下:
[‘迦百農’, ‘綠皮書’, ‘馴龍高手3’, ‘速成家庭’, ‘阿麗塔:戰斗天使’, ‘膚色’, ‘死亡天使’, ‘黎明墻’, ‘小小巨人’, ‘出·路’]
其中最關鍵的是解析網頁內容,主要是(‘//td[@class=”title”]//a/text’)這行代碼,大多數人可能對比較困惑。
這涉及到HTML網頁的結構,可以把網頁理解成一個文件夾,打開一個文件夾,會發現子文件夾,子文件夾或許還有文件夾。通過打開一個個文件夾,最終找到需要的數據。
至于是怎么寫出來這行代碼的,可以通過在網頁空白處點擊右鍵,查看源代碼,就可以找到對應的td、class=”title”、a等標識符。
大多數程序員寫爬蟲選擇python的理由很簡單.
首先,python有很多的庫,可以直接調用,比如:上面的代碼就引入了requests、lxml庫,分別實現訪問網頁、對網頁結構解析。有開源的庫,就直接調用,避免重復造輪子。
其次,python寫起來很方便,配置也簡單,短短幾行的代碼,就可以直接運行了,如果使用C或者Java,可能配置環境就要老半天。
把上面的每個步驟分別實現(模塊化),就可以構成一個簡答的爬蟲系統。
使用URL(可以理解為網址鏈接)管理器管理所有的網址鏈接,使用HTML(可以理解為網頁內容)下載器下載網頁內容,使用HTML解析器對下載的內容解析,再加上數據存儲模塊、控制整個爬蟲的調度模塊,就構成了一個簡單的爬蟲系統。
更具體的說,URL管理器負責管理所有的網址鏈接,記錄下哪些URL已經爬取了,哪些還沒有爬取。如果爬取過了,就要避免再次下載,如果沒有,就要加入隊列,等HTML下載器下載。
HTML下載器可以從服務器下載整個網頁的內容,從URL管理器中獲取未爬取的網址鏈接,之后,訪問這些網頁鏈接,下載網頁。
HTML解析器負責解析下載好的網頁,主要有兩個任務:一方面,解析出需要的信息,比如上文的“一周口碑榜”;另一方面,解析出新的URL鏈接,交給URL管理器,繼續下載,這個功能在上面的“7行代碼”沒有實現。
數據存儲器實現存儲數據的功能,將HTML解析器解析出來的信息存儲起來,否則每次使用都要下載,會浪費大量的時間。圖片、文檔之類的文件可以直接保存到服務器上,文字類的可以通過數據庫存儲起來。
爬蟲調度器作為系統的大腦,負責統籌其他四個模塊的協調工作。
無論是大型的還是小型的爬蟲雖然在設計細節,性能上有所不同,但都不會脫離這五個模塊。
乍一看,每個模塊實現起來都很簡單,但細想,似乎每個模塊都要考慮很多東西。
7行代碼爬取豆瓣電影,直接訪問網址鏈接(https://movie.douban.com/)就可以爬取“一周口碑榜”。對稍大一些的爬蟲系統或者商用爬蟲,就要有更多的考慮了,在保證獲取充足信息的同時,也要保證下載的質量。
對搜索引擎公司而言,要盡可能包括互聯網所有的信息。對垂直領域,更多的偏向業務類信息,比如:對新聞類的APP,主要包括一些新聞網站、政府網站等,對Github這類的編程網站,他們可能就不感興趣。
巧婦難為無米之炊,初始的網址鏈接基本要靠人工憑經驗獲取,比如:新聞類的APP,他們的初始URL列表里可能就包括新浪、網易、搜狐等門戶網站,也包括各個級別的政府網站,還有人民網、新華社、人民日報等媒體的網站。
當一個頁面下載完成后,從這個網頁中提取出其中的網址鏈接,把它們添加到等待下載的隊列中,就可以獲得更多的網址鏈接。
如果一個網頁已經下載過了,重新下載,會消耗大量的時間,并占用存儲空間。更要命的是,如果一直重復下載,就可能陷入死循環。
那么,如何知道這網址鏈接是不是已經下載過了?
對于小型爬蟲,可以使用列表存儲下載過的網址鏈接,當有新的網址鏈接的時候,先查找這個列表中有沒有該網址鏈接。如果有的話,就不用插入,如果沒有的話,就插入列表,等待訪問下載。
對于大型爬蟲,有成百上千個“小爬蟲”(更加專業的名詞叫做分布式爬蟲),分布在不同的服務器上,同時爬取網址鏈接,就要考慮更多的東西。
比如:不同爬蟲之間的分工和通信,如何共同維護上述的列表。
當數據很大的時候,就要考慮分布式、通信、存儲、帶寬等每個環節的限制,無論哪個環節沒有做好,都有可能成為系統的瓶頸,這就像是木桶效應中的短板。
數據量增加10倍,之前的代碼可能要重寫了,工作量可能就要增加100倍,這也是量變引起質量的一個很好的例子。
在計算機領域,這樣的例子隨處可見,當數據增大到一定量級,原有的算法很可能無法繼續使用,需要重新開發,隨之而來的是加班、DEBUG以及延期上線。
爬取豆瓣電影的“一周口碑榜”,需要研究網頁的源代碼,并編寫對應的解析代碼。但是網頁的結構不同,用這個代碼爬取知乎,解析不到任何內容。
以新聞類的APP為例:一個好的新聞類APP需要爬蟲數以億計的網頁,并把里面的文字、視頻、圖片分別解析出來,難度可想而知。
好消息是一部分網站會遵守RSS規范(遵守RSS規范的網頁結構和代碼都有相似性,以便于訂閱器獲取主要信息),一種類型的爬蟲就可以爬取大量這種類似的網頁。但大部分的網站的結構,都是不同的,這需要算法工程師花費大量的時間和精力做解析工作。
新聞類APP通過爬蟲,獲得大量的優質資源,讀者也樂意在一個平臺上看到所有的內容,但“被爬取”的網站就不太高興了。對于大多數依靠廣告收入的網站,沒有了流量,連生存都成了問題,更別說盈利了。
一些自成體系的平臺,比如:大型電商平臺,他們希望所有的用戶在自己的平臺上查找信息,所有的商家在自己的平臺上吸引賣家(廣告費可不能付給搜索引擎),同樣不希望爬蟲的騷擾。
搜索引擎希望爬取更多的信息,優質的內容提供商又不希望被爬蟲騷擾,利益沖突難以調和,于是產生了Robots協議來解決這個問題。
Robots協議網站服務器的一個聲明,通常是保存在網站根目錄下的一個TXT格式的文件,網站通過Robots協議告訴搜索引擎:哪些頁面可以抓???哪些頁面不能抓???
當爬蟲訪問一個站點時,它會首先檢查該站點根目錄下是否存在robots.txt,如果存在,爬蟲就會按照該文件中的內容來確定訪問的范圍;如果該文件不存在,所有的爬蟲將能夠訪問網站上所有沒有被口令保護的頁面。
我們使用搜索引擎,經常會看到“由于該網站的robots.txt文件存在限制指令(限制搜索引擎抓取),系統無法提供該頁面的內容描述”,就是源于這個協議。
值得注意的是:Robots協議是國際互聯網界通行的道德規范,并沒有強制性約束力。
一些“沒有道德”的爬蟲同樣會爬取有robots.txt限制指令的網站,這時候就需要一些技術來實現反爬蟲了。
最常見的有三種方式:
每個電腦都有唯一的IP地址,每個爬蟲也有唯一的IP地址,當電腦或者爬蟲訪問網站的時候,網站會記錄這個IP地址。如果同一個IP短時間多次訪問同一個網站,這個網站可能會傾向于認為這是個爬蟲,會采取一些措施。
當然,這在反爬蟲的同時,也會給用戶帶來一些不好的體驗。
相比之下,一些比較優秀的網站或者APP,會根據用戶點擊頻率、時間間隔等信息,判斷是不是爬蟲或者誤點擊,之后再確定是否需要驗證。
更好的用戶體驗背后,是更大的開發成本,更長的開發周期。
當我們使用瀏覽器訪問網站的時候,瀏覽器會自動在訪問請求上添加一些信息,比如:瀏覽器采用的編碼方式、使用的操作系統、瀏覽器版本等信息放在訪問請求的最開始,作為Headers,但爬蟲一般不會附加這些信息。
網站會根據是否存在Headers信息以及Headers信息的內容,判斷對方是不是爬蟲,有必要的話,就拒絕訪問。
之前將的HTML網頁都是靜態的,隨著HTML代碼生成,頁面的內容和顯示效果就不會發生變化了。而動態網頁則不然,動態網站是腳本語言(比如PHP)生成的,一些內容不是直接可見的,而是要運行一些腳本,才能看到。
網址后綴為htm、html、shtml、xml的網頁是靜態網頁,而動態網頁是以·aspx、.asp、.jsp、.php、.perl、.cgi等形式為后綴,并且在動態網頁網址中有一個標志性的符號“?”,這些不同的后綴基本代表了網頁使用的語言。
訪問靜態網頁,只需要直接訪問鏈接就可以了,訪問動態網站,還需要執行一些特定的操作(比如點擊),才能顯示更多的內容,這就增加了爬取的難度,一些簡單的爬蟲就被拒之門外了。
介紹完三種主流的反爬蟲的方式,最后要說的是:反爬蟲技術也不是一勞永逸的,在反爬蟲的發展過程中,爬蟲也進化出了一系列反“反爬蟲”的方式。
針對反爬蟲驗證IP機制,爬蟲“進化”出了IP代理池,這樣,爬蟲就可以不斷變換自己的IP地址,迷惑反爬蟲。針對Headers驗證,爬蟲也會生成一個Headers信息,甚至針對動態頁面,也會模擬瀏覽器的行為。
雖然如此,反爬蟲在一定程度上提高了爬蟲的成本,降低了爬蟲的效率,就可以將一大部分爬蟲擋在門外。
從爬蟲與反爬蟲的例子也可以看出:大多數時候,沒有絕對的有效方式。提高對方的成本,讓對方覺得代價太大,得不償失,就是很好的解決問題的辦法。
上面講了爬蟲是怎么運行的,常見的反爬蟲機制。最后,我們再講一個爬蟲的應用場景的例子,可以幫助我們更好理解爬蟲。
冷啟動是每一個產品經理、運營人員和創業者面臨的重大問題。沒有優質的內容,就吸引不了用戶,沒有大量的用戶,就無法吸引優質的內容,就陷入了先有雞還是先有蛋的悖論。
爬蟲,低成本、快速地解決了這個問題!
“我們不生產新聞,我們只是新聞的搬運工”,通過爬蟲,低成本、快速地爬取整個互聯網的優質內容,并憑借海量數據,利用算法實現內容分類和個性推薦(個性推薦系統會在后序章節詳細介紹),吸引大量的用戶,最終通過廣告變現。
事實證明,這是個非常成功的商業模式。而媒體平臺和新聞網站雇傭大量編輯人員,花費大量時間、金錢寫成的高質量內容,連說一聲都沒有,就這樣被拿走了,這不是侵犯人家版權嘛!
于是,多家媒體聯合發起侵權訴訟或抗議聲討,最終迫使這家新聞巨頭支付版權費,但無論法律上、道德上有多少問題,都不影響這家公司商業成功的既定事實。
類似的事情同樣發生在其他垂直領域。
一家新成立的技術博客平臺,爬取競爭對手上的文章,迅速實現優質內容的聚合。如果原博客主發現了自己的文章被盜用了,新的平臺就移交賬號并看情況給予少許補償。如果對方不樂意,就注銷賬號,當一切都沒有發生過。憑借這種運營方式,順利實現了冷啟動。
短視頻APP的后來者,也可以通過類似的方式,實現用戶的積累和優質內容的聚合。
勝利即正義?
這似乎是過于武斷的一個評價。
上述的視頻APP做得太過分,引起公憤,最終不得不關閉自己的平臺。
對于通過爬蟲獲取內容的平臺而言,內容的獲取也只是萬里長征的第一步,通過運營手段減小生產內容的成本,通過利益共享激勵優質內容的產生,通過技術減小信息成本吸引用戶,更加任重而道遠。
而版權,也始終是懸于頭頂的達摩克利斯之劍。
本文由@linghu 原創發布于人人都是產品經理,未經許可,禁止轉載
題圖來自Unsplash, 基于CC0協議
鳥學ASP
學習目的:安裝調試ASP的環境,并且調試第一個簡單的程序。
因為我們學ASP的目的就是想建立一個網站,那么一般習慣是建立的網站內所有文件應該同時放到一個文件夾中(當然這個文件夾中還可以按需要設置子文件夾!),所以在這里我在E盤建立一個myweb的文件夾。
首先來安裝Windows 2000/XP自帶的IIS作為服務器。在這里因為我的機器是XP所以所有截圖都是XP下完成的。
控制面板-->>添加或刪除程序。
然后是添加刪除windows組件-選中IIS組件前面的勾,之后等待安裝,這里可以觀看本站以前給大家做的視頻教程,完成安裝后。
之后在控制面板中雙擊“管理工具”。
然后雙擊“internet信息服務”,這就是IIS。
選擇“默認網站”,然后右鍵屬性或者直接按快捷鍵
在屬性頁面內只有三個頁面需要修改,先是網站,如果用戶有固定IP,可以分配一個IP
接下來在注主目錄中選擇一個自己硬盤上面的文件夾存放網站(這個目錄就是我們上面說的在e盤建立的目錄),選中讀取、寫入
在文檔中添加默認的頁面,比如打http://www.liexiaow.com獵校網 調用了一個默認文檔即是你添加的頁面。
接下來也是最關鍵的:
1、在剛才你定義的一個文件夾里面新建一個文件,可以用記事本建立一個文本文件然后把下面的內容復制到記事本中:
<%response.write "hello world!"%>
保存為1.asp文件(注意:.asp不能省略啊,如果省略了你就保存了一個文本文件了)。
最后打開IE,在地址欄內輸入:http://127.0.0.1/1.asp(或者http://localhost/1.asp)回車后就可以看到效果了。
最后解釋一下代碼的含義。
response.write就是顯示的意思,前后的 <% 和 %> 是asp的標記符號,在這里面的信息都由服務器處理。127.0.0.1是地址,1.asp是文件名。第一天就結束了!
表單元素要放在一個表單域里面,建立一個表單域。然后修改動作里面的文件為要接受這個表單變量的ASP文件。方法有兩種,一種是POST,這個方法傳送的變量不會在瀏覽器的地址欄里面顯示,可以大批量傳送數據;GET則是會在瀏覽器地址欄里面顯示的,等一會舉例子。
下面我們看一個表單元素。
文本域,這個是最基本的,傳送的是文本信息,一般用戶名,密碼都要用這個傳送,不過要是密碼的話要在類型里面選擇密碼,這樣就會以*代替顯示出來的字符,文本域的名字很重要,以后會用到這個名字所以一般不用默認的名字。
現在舉一個例子:如果文本域的名字是name的話,用來傳送網上用戶登記的名字,在表單域里面,傳送到reg.asp,用POST方法,那么在reg.asp里面這樣得到變量<%name=request.form("name")%>如果要顯示變量再家加一句,response.write name,這樣就形成了一個從客戶端到瀏覽器再回到客戶端的過程。如果方法用的是GET的話,那么就改為name=request.querystring("name")實際上兩者可以統一為name=request("name")。下面看看按鈕,按鈕里面無非兩種,一種是提交表單的按鈕,一種是重新輸入的按鈕。單選按鈕,一個按鈕有一個值。在列表里面同樣,添加列表選項和值。下面舉一個例子,實際上各種表單元素都是差不多的。
下面是具體的代碼: (注:把下面代碼保存為一個.htm的文件就可以了.我保存的1.htm)
<form name="form1" method="post" action="reg.asp">
姓名:
<input type="text" name="name"> //文本域,名字叫name
<br>
密碼:
<input type="password" name="psw"> //文本域,用來輸入密碼,名字叫psw
<br>
<br>
性別:
<input type="radio" name="sex" value="男"> //單選,名字叫sex,數值是"男"
男
<input type="radio" name="sex" value="女"> //單選,名字叫sex,數值是"女"
女 <br>
<br>
城市:
<select name="city">
<option value="上海" selected>上海</option> //復選,大家自己分析一下
<option value="北京">北京</option>
</select>
<br>
<input type="submit" name="Submit" value="提交"> //提交按鈕
<input type="reset" name="Submit2" value="重置">
</form>
下面是reg.asp的代碼,用來顯示出剛才受到的信息:
<%
name=request.form("name")
psw=request.form("psw")
sex=request.form("sex")
city=request.form("city")
response.write name
response.write psw
response.write sex
response.write city
%>
打開瀏覽器在地址欄內輸入:http://localhost/1.htm如下圖:(呵呵,因為是練習,我沒有美化頁面?。。?/p>
下面我們要開始學數據庫了!只要把表單和數據庫相應的字段連接上就可以了。
學會ACCEES數據庫的使用。
首先,要安裝OFFICE里面的ACCEES(我的演示是OFFICE 2003版本),安裝過程這里就不說了,安裝好以后會,打開Access.按空數據庫,新建一個數據庫,文件名字可以叫guestbook.mdb。(提示:為了安全期間,文件名復雜一點好,因為ACCESS數據庫可以被下載的!?。?/p>
使用設計器創建新的表,一個數據庫MDB文件里面可以建立多個表。雙擊“使用設計器創建表”
填寫字段名字然后選擇字段類型,一條記錄可以有很多字段,可以有很多字段類型,字段大小的意思就是這個字段最多可以容納的字符數,當這個字段沒有任何信息是,ACCEES會用默認值代替(沒有任何信息不是空的意思),一般必填字段和允許空字符串分別設置為否、是,以防止出錯
按照上圖分別建立幾個字段,在時間中默認值為=now()就是這個字段不需要填寫,系統直接以當前時間代替。
所以的字段都建立以后,關閉這個窗口,按提示保存表,輸入表的名字guest,最后出現下圖的提示,選擇是,主鍵是記錄的標識,為了以后簡單,大家可以把編號改為ID,還有在ACCEES里面盡量不要用中文表示字段名字
最后,雙擊打開這個表,觀看表里面的記錄
握ACCESS數據庫的連接和讀取記錄
首先還打開我們上一節課建立的數據庫中的表,隨便輸入幾條記錄,如下圖:
這節課學習的內容有一點枯燥,但是很重要。在這里不需要知道命令具體的運行情況,外面的很多書籍之所以不適合入門就是因為介紹了太多的理論知識,讓初學者一頭霧水。
下面開門見山,看兩行代碼:
<%
set conn=server.createobject("adodb.connection")
conn.open "driver={microsoft access driver (*.mdb)};dbq="&server.mappath("data/guestbook.mdb")
%>
第一行定義了一個adodb數據庫連接組件,第二行連接了數據庫,大家只要修改后面的數據庫名字就可以了。是不是很簡單?
下面再看三行:
<%
exec="select * from guest"
set rs=server.createobject("adodb.recordset")
rs.open exec,conn,1,1
%>
這三行加在前面兩行的后面,第一句:設置查詢數據庫的命令,select后面加的是字段,如果都要查詢的話就用*,from后面再加上表的名字,我們前面建立的是不是一個gust表阿?第二句:定義一個記錄集組件,所有搜索到的記錄都放在這里面,第三句是打開這個記錄集,exec就是前面定義的查詢命令,conn就是前面定義的數據庫連接組件,后面參數“1,1”,這是讀取,后面講到修改記錄就把參數設置為1,3,好了接下來我們讀取記錄。
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<%do while not rs.eof%><tr>
<td><%=rs("name")%></td>
<td><%=rs("tel")%></td>
<td><%=rs("message")%></td>
<td><%=rs("time")%></td>
</tr><%
rs.movenext
loop
%>
</table>
//下面的三條語句是用于關閉數據庫
rs.close
set rs=nothing
conn.close
set conn=nothing
在一個表格中,我們用4列分別顯示了上次建立的表里面的四個字段,用do循環,not rs.eof的意思是條件為沒有讀到記錄集的最后,rs.movenext的意思是顯示完一條轉到下面一條記錄,<%=%>就等于<%response.write%>用于在html代碼里面插入asp代碼,主要用于顯示變量。
把上面三段代碼依次復制粘貼到剪貼板中,一定要按順序復制粘貼?。?,然后保存為duqu.asp就可以了!打開瀏覽器,在地址欄內輸入:http://localhost/duqu.asp.
下面是我機器上面的結果圖片。
學會數據庫的基本操作--寫入記錄
數據庫的基本操作無非是:查詢記錄,寫入記錄,刪除記錄,修改記錄。
今天我們先學習寫入記錄。先建立一個表單:(把下面文章保存為5.htm)
<form name="form1" method="post" action="exa5.asp">
name <input type="text" name="name"><br>
tel <input type="text" name="tel"><br>
message <input type="text" name="message" value=""><br>
<input type="submit" name="Submit" value="提交">
<input type="reset" name="Submit2" value="重置">
</form>
表單提交到exa5.asp,下面是exa5.asp的代碼: (把下面代碼保存為5.asp)
<%
set conn=server.createobject("adodb.connection")
conn.open "driver={microsoft access driver (*.mdb)};dbq="&server.mappath("data/guestbook.mdb")
name=request.form("name")
tel=request.form("tel")
message=request.form("message")
exec="insert into guest(name,tel,message)values('"+name+"',"+tel+",'"+message+"')"
conn.execute exec
conn.close
set conn=nothing
response.write "記錄添加成功!"
%>
在這里前面兩句我不說了,后面三句我也不說了,前面說過exec里面的是執行的命令,添加記錄的比較繁,大家要仔細看。
insert into后面加的是表的名字,后面的括號里面是需要添加的字段,不用添加的或者字段的內容就是默認值的可以省略。注意,這里的變量一定要和ACCESS里面的字段名對應,否則就會出錯。values后面加的是傳送過來的變量。exec是一個字符串,"insert into guest(name,tel,message)values('"是第一段,在ASP里面不能嵌雙引號,所以可以用'代替雙引號,放在雙引號里面,連接兩個變量用+或者&所以"',"又是一段,中間夾了一個name就是表單傳來的變量,這樣就可以在這個變量外面加兩個'',表示是字符串了,后面的tel是數字型變量所以不需要外面包圍'',大家慢慢分析這句話,如果用表單傳來的數據代替變量名字的話這句話為(假設name="aaa",tel=111,message="bbb"):"insert into guest(name,tel,message)values('aaa',111,'bbb')"。
接下來的conn.execute 就是執行這個exec命令,最后別忘記把打開的數據庫關閉,把定義的組件設置為空,這樣可以返回資源。
下面幾條語句用于關閉數據庫的代碼:
rs.close
set rs=nothing
conn.close
set conn=nothing
記住,次序不可以顛倒! 可以到數據庫里面去看一看,或者用duqu.asp讀取看看是不是多了記錄阿?下面是我利用上一節的文件讀取數據庫的圖:
學會數據庫的基本操作--查詢記錄
在第四天中我們用到下面這樣一個程序:
<%
set conn=server.createobject("adodb.connection")
conn.open "driver={microsoft access driver (*.mdb)};dbq="&server.mappath("data/guestbook.mdb")
exec="select * from guest"
set rs=server.createobject("adodb.recordset")
rs.open exec,conn,1,1
%>
我們查詢的是所有的記錄,但是我們要修改、刪除記錄的時候不可能是所有記錄,所有我們要學習檢索合適的記錄。先看一條語句:
a="aaa"
b=1111110
exec="select * from guestbook where name='"+a+"'and tel="+b
where后面加上的是條件,與是and,或是or,我想=,<=,>=,<,>的含義大家都知道吧。這句話的意思就是搜索name是“aaa”的,并且電話是“1111110”的記錄。還有一點就是如果要搜索一個字段里面是不是包含一個字符串就可以這么寫:where instr(name,a)也就是搜索name里面有a(aaa)這個字符串的人。
我這里的a,b,是常量,大家可以讓a,b是表單提交過來的變量,這樣就可以做一個搜索了。
下面大家看看這個代碼,理解一下:(把下面代碼存為6.htm文件)
<form name="form1" method="post" action="exam6.asp">
搜索:<br>
name =
<input type="text" name="name">
and tel=
<input type="text" name="tel">
<br>
<input type="submit" name="Submit" value="提交">
<input type="reset" name="Submit2" value="重置">
</form>
exam6.asp(把下面代碼存為exam6.asp)
<%
name=request.form("name")
tel=request.form("tel")
set conn=server.createobject("adodb.connection")
conn.open "driver={microsoft access driver (*.mdb)};dbq="&server.mappath("data/guestbook.mdb")
exec="select * from guest where name='"+name+"' and tel="+tel
set rs=server.createobject("adodb.recordset")
rs.open exec,conn,1,1
%>
<html>
<head>
<title>無標題文檔</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<%
do while not rs.eof
%><tr>
<td><%=rs("name")%></td>
<td><%=rs("tel")%></td>
<td><%=rs("message")%></td>
<td><%=rs("time")%></td>
</tr>
<%
rs.movenext
loop
%>
</table>
</body>
</html>
首先在瀏覽器中輸入http://localhost/6.htm如下圖所示:
學會數據庫的基本操作--刪除記錄
開門見山,大家直接看程序。
exec="delete * from guest where id="&request.form("id")
上面這句話完成了刪除記錄的操作,不過鎖定記錄用了記錄唯一的表示id,我們前面建立數據庫的時候用的是系統給我們的主鍵,名字是編號,由于是中文的名字不是很方便,大家可以修改為id,我已經修改了??!
不修改的話就是用下面的代碼了:
exec="delete * from guestbook where 編號="&request.form("id")
下面我們看完整的代碼:一個表單傳給ASP文件一個ID,然后這個ASP文件就刪除了這個ID。
7.htm:
<form name="form1" method="post" action="exam7.asp">
請輸入刪除的ID號:
<input type="text" name="id">
<input type="submit" name="Submit" value="提交">
</form>
exam7.asp:(可以先運行這個文件看一下所有記錄的ID和想刪除記錄的ID,刪除記錄以后也可以通過這個文件復查。)
<%
set conn=server.createobject("adodb.connection")
conn.open "driver={microsoft access driver (*.mdb)};dbq="&server.mappath("data/guestbook.mdb")
exec="select * from guest"
set rs=server.createobject("adodb.recordset")
rs.open exec,conn,1,1
%>
<html>
<head>
<title>無標題文檔</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<%
do while not rs.eof
%><tr>
<td><%=rs("id")%></td>
<td><%=rs("name")%></td>
<td><%=rs("tel")%></td>
<td><%=rs("message")%></td>
<td><%=rs("time")%></td>
</tr>
<%
rs.movenext
loop
%>
</table>
</body>
</html>
學會數據庫的基本操作--修改記錄
先來看代碼:(存為exam8.asp就可以了)
<%
set conn=server.createobject("adodb.connection")
conn.open "driver={microsoft access driver (*.mdb)};dbq="&server.mappath("data/guestbook.mdb")
exec="select * from guest where id="&request.form("id")
set rs=server.createobject("adodb.recordset")
rs.open exec,conn
%>
<form name="form1" method="post" action="modifysave.asp">
<table width="748" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>name</td>
<td>tel</td>
<td>message</td>
</tr>
<tr>
<td>
<input type="text" name="name" value="<%=rs("name")%>">
</td>
<td>
<input type="text" name="tel" value="<%=rs("tel")%>">
</td>
<td>
<input type="text" name="message" value="<%=rs("message")%>">
<input type="submit" name="Submit" value="提交">
<input type="hidden" name="id" value="<%=request.form("id")%>">
</td>
</tr>
</table>
</form>
<%
rs.close
set rs=nothing
conn.close
set conn=nothing
%>
到現在應該分析這個代碼沒有什么問題了吧,這個代碼的作用是接受前面一個頁面的ID然后顯示這條記錄,文本框即是輸入的地方也是顯示的地方,如果需要修改的話修改以后按提交;如果不需要修改就可以直接按提交按鈕。
在這里因為本教程適合初學的,所以也把提交的表單內容給出來,把下面代碼存為8.htm文件
<form name="form1" method="post" action="exam8.asp">
請輸入要修改的記錄的ID:
<input type="text" name="id">
<br>
<input type="submit" name="submit" value="提交">
</form>
這里還有一個東西以前沒有說,那就是隱藏的表單元素:hidden元素,里面的value是不用用戶輸入的,會隨著表單一起提交,用于傳遞變量。
下面是modifysave.asp的代碼:
<%
set conn=server.createobject("adodb.connection")
conn.open "driver={microsoft access driver (*.mdb)};dbq="&server.mappath("data/guestbook.mdb")
exec="select * from guest where id="&request.form("id")
set rs=server.createobject("adodb.recordset")
rs.open exec,conn,1,3
rs("name")=request.form("name")
rs("tel")=request.form("tel")
rs("message")=request.form("message")
rs.update
rs.close
set rs=nothing
conn.close
set conn=nothing
%>
在這里,rs.open exec,conn,1,3后面的參數是1,3,這我以前提過,修改記錄就要用1,3。實際上修改記錄很容易看懂,記錄集是rs,rs("aa")就是當前記錄aa字段的東西,讓它等于新的數據request.form("aa")當然就修改了,不過最后別忘記保存,那就是rs.update!
說到這里,記錄的搜索,讀取,修改,插入都說了,通過這最基本的東西就可以作出復雜的東西了,外面的大型數據庫:新聞系統,留言簿就是字段多一點罷了。今天的示例中的代碼是結合以前的數據庫的,以后回去調試分析一下。
大家測試的流程:首先運行8.htm文件
基本的SESSION組件,總結response,request組件。
首先,有會員系統的任何程序都會用到檢測是不是用戶已經登陸這個步驟。這就用到了SESSION組件,下面我們 看一個代碼來說明。
<%
session("login")="yes"
%>
這句話的意思就是在session里面定義一個login字符串變量,值為"yes",直接可以賦值,不需要聲明。是不是很簡單?
如果我們做管理員登陸系統的話,首先是一段檢測是不是管理員:
if 是 then
session("isadmin")=yes"
else
session("isadmin")="no"
end if
在每一個需要管理員才能看的頁面最前面加上:
<%
if not session("isaadmin")="yes" then
response.redirect "login.htm"
%>
這樣一般用戶就無法打開這個頁面。解釋一下response.redirect,它是轉向的意思,后面的"login.htm"就是轉向的文件。這樣沒有登陸的管理員是無法看到后面的內容的。
response組件基本就是用到response.write(),response.redirect() 分別是寫字符串和轉向的作用。
request基本就是request.form(),request.querystring() 分別是接受post,get方法傳來的信息。
最后我們一起來制作一個簡單的后臺登陸管理界面,首先在myweb目錄下建立一個admin文件夾,然后我們建立一個數據庫名字為admin.mdb,然后我們再建立一個表,表中設置兩個字段name,password,類型都是文本型的!最后退出時設置主鍵,保存為表名check。然后可以輸入一條記錄用戶名:admin,密碼:admin。具體建立數據庫的方法請看《菜鳥十天學會ASP教程之第三天:數據庫的建立》
下面我們開始編寫ASP程序,首先建立一個index.asp(管理主界面)程序,代碼如下:
<%@language=vbscript%>
<%if not session("checked")="yes" then
response.Redirect "login.asp"
else
%>
<html>
<head>
<title>管理界面</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<frameset cols="167,*" frameborder="YES" border="1" framespacing="1" rows="*" bordercolor="#666666">
<frame name="leftFrame" scrolling="auto" noresize src="left.asp">
<frame name="mainFrame" src="right.asp">
</frameset>
<noframes>
<body bgcolor="#FFFFFF" text="#000000">
</body>
</noframes>
</html>
<%end if%>
在上面的代碼中,大家可以看到用到login.asp,left.asp,right.asp程序
login.asp://登陸系統程序
<html>
<head>
<title>管理員入口</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<style type="text/css">
<!--
.topic { font-family: "宋體"; font-size: 11pt; font-weight: bold; color: #FFFFFF}
.font { font-family: "宋體"; font-size: 10pt; font-weight: normal; color: #000000}
.table { border-color: #666666 black; border-style: solid; border-top-width: 1pt; border-right-width: 0px; border-bottom-width: 1pt; border-left-width: 0px}
.text { border: 1pt #999999 solid; height: 15pt}
-->
</style>
</head>
<body text="#000000" topmargin="0" bgcolor="#FFFFFF">
<table width="100%" border="0" cellpadding="0" cellspacing="0" align="center" height="100%">
<tr>
<td height="129" valign="top" colspan="3"> </td>
</tr>
<tr>
<td width="230" height="170" valign="top"> </td>
<td valign="top" width="277">
<table width="100%" border="0" cellspacing="1" cellpadding="0" height="100%" bgcolor="#000000" align="center">
<tr>
<td align="center" valign="middle" height="167">
<form name="form1" method="post" action="check.asp">
<table width="100%" border="0" cellspacing="0" cellpadding="0" height="100%">
<tr bgcolor="#62892C">
<td height="31" class="topic" colspan="2">
<div align="center">管理員入口<br>
</div>
</td>
</tr>
<tr>
<td bgcolor="#87bc3c" colspan="2" class="table">
<div align="center"> <span class="font"> 管理員:</span>
<input type="text" name="name" class="text" size="20" onMouseOver="this.focus()">
<br>
<span class="font">密 碼:</span>
<input type="password" name="password" class="text" size="20" onMouseOver="this.focus()"><%if session("check")="wrong" then response.Write "<br><span class='font'><font color=red>驗證錯誤!</font></span>" end if%>
</div>
</td>
</tr>
<tr>
<td bgcolor="#87bc3c" width="52%">
<div align="center" class="font">
<input type="reset" name="Submit2" value="重置" class="text">
</div>
</td>
<td bgcolor="#87bc3c" width="48%">
<div align="center" class="font">
<input type="submit" name="Submit22" value="提交" class="text">
</div>
</td>
</tr>
</table> </form>
</td>
</tr>
</table>
</td>
<td width="241" valign="top"> </td>
</tr>
<tr>
<td height="123" valign="top" colspan="3"> </td>
</tr>
</table>
</body>
</html>
在上面的程序中用到一個檢查用戶和密碼是否正確的程序check.asp://核對輸入的用戶和密碼是否正確
<%
dim name,password
name=request.form("name")
password=request.form("password")
dim exec,conn,rs
exec="select *from check where(name='"&name&"' and password='"&password&"')"
set conn=server.createobject("adodb.connection")
conn.open "driver={microsoft access driver (*.mdb)};dbq="&server.mappath("admin.mdb")
set rs=server.createobject("adodb.recordset")
rs.open exec,conn
if not rs.eof then
rs.Close
conn.Close
session("checked")="yes"
session("check")="right"
response.Redirect "index.asp"
else
session("checked")="no"
session("check")="wrong"
response.Redirect "login.asp"
end if
%>
left.asp://管理導航
<%@language=vbscript%>
<%if not session("checked")="yes" then
response.Redirect "login.asp"
else
%>
<html>
<head>
<title>管理界面</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body text="#000000" topmargin="0" bgcolor="#ffffff" leftmargin="10">
<div align="center"><a href="index.asp" target="_parent"><br>
<br>
管理界面首頁</a> <a href="exit.asp" target="_parent">退出</a><br>
<br>
</div>
</body>
</html>
<%end if%>
exit.asp://退出系統
<%@language=vbscript%>
<%
session("check")=""
session("checked")=""
response.redirect "login.asp"
%>
right.asp://具體管理的內容
<%@language=vbscript%>
<%if not session("checked")="yes" then
response.Redirect "login.asp"
else
%>
<html>
<title>管理界面</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body bgcolor="#ffffff" text="#000000" topmargin="20" class="title">
這里是網頁教學網的管理系統示例!請大家多研究使用!
</body>
</html>
<%end if%>
運行時首先運行index.asp程序,運行效果部分截圖如下:
分頁技術
今天最后一天我們學習一下ASP里面稍微難一點地分頁技術,畢竟當我們有N條記錄的時候我們不可能把所有記錄顯示在一個頁面里面吧。
<%
exec="select * from test"
set rs=server.createobject("adodb.recordset")
rs.open exec,conn,1,1
rs.PageSize=3
pagecount=rs.PageCount
page=int(request.QueryString ("page"))
if page<=0 then page=1
if request.QueryString("page")="" then page=1
rs.AbsolutePage=page
%>
rs.pagesize設置一個頁面里面顯示的記錄數,pagecount是我們自己定義的一個變量,rs.pagecount是記錄的個數,page也是我們自己定義的一個變量,我們下一頁的鏈接可以設置為list.asp?page=<%=page+1%>,下一頁的鏈接可以設置為list.asp?page=<%=page-1%>,這樣當按下鏈接的時候調用頁面自己,page這個變量就+1或者-1了,最后我們讓rs.absolutepage(當前頁面)為第page頁就可以了。
if request.QueryString("page")="" then page=1,這句話的作用就是我們打開list.asp的時候沒有跟隨page變量,自動設置為page=1,防止出錯,還有當我們if....then...放在一行的時候end if可以省略。是不是分頁也不難?
下面說一種特殊情況:
if page=1 and not page=pagecount,這個時候沒有上一頁,但是有下一頁
elseif page=pagecount and not page=1,這個時候沒有下一頁,但是有上一頁
elseif page<1,這個時候沒有任何記錄
elseif page>pagecount then,這個時候沒有任何記錄
elseif page=1 and page=pagecount,這個時候沒有上一頁,沒有下一頁
else,這個時候有上一頁,也有下一頁。
下面看一段顯示1到n頁,且每一個數字點擊以后就出現這個數在代表的頁面的代碼,很常見哦。
<%for i=1 to pagecount%>
<a href="list.asp?page=<%=i%>"><%=i%></a><%next%>
for....next是循環從i=1開始,循環一次加1到pagecount為止。
最后我的實例里面包含了一個最簡單的ASP程序,但是功能樣樣有,是ASP的精髓,每一個ASP大型程序都包含了它。
add.htm增加記錄頁面
add.asp增加記錄操作
conn.asp數據庫鏈接
del.asp刪除記錄操作
modify.asp修改記錄頁面
modifysave.asp修改記錄操作
list.asp這個是這個程序的核心,通過這個頁面實現記錄的添加、修改、刪除。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。