爬行過程是深度優先的過程。設置四個初始URL,然後維護壹個數據庫。數據庫中有兩個表和壹個infoLib,存儲了抓取的主要信息:標題、URL和html。另壹個表是urlLib,它存儲已經被抓取的url。它是壹個輔助表。在我們抓取每壹個網頁之前,都需要判斷該網頁是否被抓取過(是否存在於urlLib中)。在數據存儲過程中,使用了少量的SQL語法。因為之前學過MySQL,這壹塊比較好辦。
深度優先的網頁爬取方案是:給定初始url,爬取該網頁中的所有URL,繼續遞歸爬取網頁中的URL。下面逐段分析代碼,方便妳以後復習。
1.構建壹個雜亂的項目:
關於建築工程,妳可以參考這個零碎的入門教程,通過運行:
[python]查看純文本
scrapy startproject ***
在當前目錄下創建壹個scrapy項目,然後在蜘蛛的子目錄下創建壹個. py文件,這是爬蟲的主文件。註意:文件名不能與項目名相同,否則以後調用運行此爬蟲時會出錯。請參見ImportError。
2.編寫。py文件具體來說:
[python]查看純文本
進口廢品
從廢料進口請求
導入sqlite3
類RSS pider(scrapy . spiders . spider):#這個類繼承自scrapy中的spider。
Name = "zhidao" #將爬蟲命名為" Know ",執行爬蟲時對應的指令會是:scrapy crawl zhidao。
#download_delay = 1 #只用來控制爬蟲的速度,1s/時間,可以用來對付反爬蟲。
allowed _ domains =[" zhidao . Baidu . com "]#允許抓取範圍。
Url_first = '/question/' #稍後用於解析域名的短字符串。
start _ URLs =["/question/647795152324593805 . html ",#python
"/question/23976256.html ",#database
"/question/336615223.html ",#C++
"/question/251232779.html ",#操作員系統
"/question/137965104 . html " # Unix編程
] #定義初始url,已知初始網頁有五種類型。
#添加數據庫
conn database = sqlite3 . Connect(" zhidao.db ")#連接到數據庫" zhidao . db "。
c database = conn database . cursor()#設置定位指針。
cDataBase.execute(' ' ' '如果infoLib中不存在,則創建表
(id整數主鍵自動增量,名稱文本,url文本,html文本)“”)
#通過定位指針來操作數據庫。如果zhidao.db中的infoLib表不存在,就會建立,其中主鍵是自增id(引擎的docId),下壹列是文章標題,然後是url,最後是html。
#url數據庫
cDataBase.execute(' ' ' '如果urlLib不存在,則創建表
(url文本主鍵)“”)
#通過定位指針來操作數據庫。如果zhidao.db中的urlLib表不存在,則建立,其中只保存URL,保存爬取的URL。另建表的原因是猜測表的主鍵應該存儲在哈希表中,查詢速度更快。事實上,在這裏也可以將兩個表與壹個外鍵相關聯。
2.2中的解析函數。。py文件:
中的分析函數。py文件將專門處理url返回的響應並解析它。具體守則規定:
[python]查看純文本
定義解析(自身,響應):
pagename = response . XPath('//title/text()')。extract () [0] #解析已爬網網頁中的名稱。
pageUrl = response . XPath("//head/link ")。re('href= "(。*?)" ')[0] #解析抓取的網頁的url,而不是直接用函數獲取,這樣會夾雜亂碼。
page html = response . XPath("//html ")。extract () [0] #獲取網頁html。
#判斷pageUrl是否處於卷曲狀態
如果pageUrl在self.start_urls中:
#如果當前url是start_url的成員。之所以這樣判斷,是因為在重復的start_url中我們還是會爬取網址,但是在非start_url中我們不會爬取已經爬取過的網頁。
self . c database . execute(' SELECT * FROM URL lib其中url =(?)',(pageUrl,))
lines = self.cDataBase.fetchall()
If len(lines): #如果當前Url已被爬網。
Pass #不再向數據庫添加信息,只是不斷向下爬。
否則:#否則,將信息抓取到數據庫中。
self . cdatabase . execute(' INSERT INTO URL lib(URL)VALUES(?)',(pageUrl,))
self . c database . execute(" INSERT INTO infoLib(name,url,html) VALUES(?,?,?)",(頁面名稱,頁面Url,頁面Html))
Else: #此時進入的非url網頁壹定沒有被抓取過(因為會先判斷深入start_url後的網頁,抓取時會在下面的for循環中判斷)。
self . cdatabase . execute(' INSERT INTO URL lib(URL)VALUES(?)',(pageUrl,))
self . c database . execute(" INSERT INTO infoLib(name,url,html) VALUES(?,?,?)",(頁面名稱,頁面Url,頁面Html))
Self.connDataBase.commit() #保存數據庫的更新。
打印“- #輸出提示信息沒用。
for sel in response . XPath('//ul/Li/a ')。re('href="(/question/。*?。html)'): #抓取本頁面所有擴展頁面,判斷並抓取未抓取的頁面。
Sel = ""+sel #解析擴展網頁的url。
self . c database . execute(' SELECT * FROM URL lib其中url =(?)',(sel,))#確定網頁是否已經在數據庫中。
lines = self.cDataBase.fetchall()
如果len(lines) == 0: #如果不是,繼續爬取。
讓步請求(url = sel,callback=self.parse)