搜索引擎課的一次小實驗~
題目是這樣的:
以指定網址為根節點,遍歷(深度優先、廣度優先)訪問 50 個頁面並爬取這些頁面上的所有網址。
代碼
import re
import requests
from requests.exceptions import ReadTimeout, ConnectionError, RequestException
import urllib3
# 使用requests訪問https時會有SSL驗證,需要在get方法時關閉驗證,同時會顯示警告
urllib3.disable_warnings() # 用該行代碼消除警告
visited = [] # 已經訪問過(爬取過)的url。訪問:即get該頁面並取出該頁面上的所有url
unvisited = [] # 已經取出的、但是還沒有訪問的/等待訪問的url
url_count = 0 # 已經訪問過的url數量
END_COUNT = 50 # 總共需要訪問的url數量
end_flag = False # 標志是否該結束了(url_count >= END_COUNT)
# 訪問頁面:獲取指定頁面中含有的url
def visit(url, depth):
visited.append(url) # 將該鏈接置為訪問過
try:
req = requests.get(url, verify=False, timeout=5) # verify參數:關閉SSL驗證
except ReadTimeout: # 超時異常
print('Timeout: ', url)
## 需要把當前的 url 放到任務中,過一段時間再嘗試連接
except ConnectionError: # 連接異常
print('Connection error: ', url)
except RequestException: # 請求異常
print('Error: ', url)
else:
if req.status_code == 404:
print('404頁面不存在: ', url)
## 把當前的 url 從爬蟲任務中刪除掉
if req.status_code == 403:
print('403頁面禁止訪問: ', url)
## ...
if req.status_code == 200:
# 如果正確訪問,count+1;判斷是否結束
global url_count
global end_flag
url_count += 1
if url_count >= END_COUNT:
end_flag = True
print("\t"*depth, "#%d-%d %s"%(depth, url_count, url))
PATTERN_URl = "<a.*href=\"(https?://.*?)[\"|\'].*"
ulist = re.findall(PATTERN_URl, req.text)
ulist = [url for url in ulist if url.find(".pdf") == -1 ] # 為了防止下載pdf文件,特意跳過了:只保留沒有".pdf"后綴的url
return ulist
return None
def dfs(url, depth=1):
ulist = visit(url, depth)
if ulist:
ulist = list(set(ulist)-set(visited)) # ulist是局部變量,指的是一個節點的所有子節點
for url in ulist:
if depth<3 and not end_flag: # 只訪問1、2、3層(根節點是第0層)
dfs(url, depth+1)
def bfs(url):
depth = 0
global unvisited
unvisited.append([url, depth])
while(unvisited): # unvisited每個元素是[url, depth]
[url, depth] = unvisited.pop(0)
# 只訪問1、2層
if end_flag or depth >= 3:
break
ulist = visit(url, depth)
if ulist:
ulist = list(set(ulist)-set(visited))
depth += 1 # ulist中的url都是當前url的孩子,所以深度加一
unvisited = unvisited + [[url, depth] for url in ulist]
if __name__ == '__main__':
start_url = "http://www.hzau.edu.cn"
strategy = input("輸入dfs/bfs:")
if strategy == "dfs":
print("\t"*0, "#%d %s"%(0, start_url))
dfs(start_url)
elif strategy == "bfs":
bfs(start_url)
else:
print("輸入格式有誤,請重新輸入")
結果截圖