爬蟲原理:
以下來自知乎解釋
首先你要明白爬蟲怎樣工作。
想象你是一隻蜘蛛,現在你被放到了互聯“網”上。那麼,你需要把所有的網頁都看一遍。怎麼辦呢?沒問題呀,你就隨便從某個地方開始,比如說人民日報的首頁,這個叫initial pages,用$表示吧。
在人民日報的首頁,你看到那個頁面引向的各種連結。於是你很開心地從爬到了“國內新聞”那個頁面。太好了,這樣你就已經爬完了倆頁面(首頁和國內新聞)!暫且不用管爬下來的頁面怎麼處理的,你就想象你把這個頁面完完整整抄成了個html放到了你身上。
突然你發現, 在國內新聞這個頁面上,有一個連結鏈回“首頁”。作為一隻聰明的蜘蛛,你肯定知道你不用爬回去的吧,因為你已經看過了啊。所以,你需要用你的腦子,存下你已經看過的頁面地址。這樣,每次看到一個可能需要爬的新連結,你就先查查你腦子裡是不是已經去過這個頁面地址。如果去過,那就別去了。
好的,理論上如果所有的頁面可以從initial page達到的話,那麼可以證明你一定可以爬完所有的網頁。
想象你是一隻蜘蛛,現在你被放到了互聯“網”上。那麼,你需要把所有的網頁都看一遍。怎麼辦呢?沒問題呀,你就隨便從某個地方開始,比如說人民日報的首頁,這個叫initial pages,用$表示吧。
在人民日報的首頁,你看到那個頁面引向的各種連結。於是你很開心地從爬到了“國內新聞”那個頁面。太好了,這樣你就已經爬完了倆頁面(首頁和國內新聞)!暫且不用管爬下來的頁面怎麼處理的,你就想象你把這個頁面完完整整抄成了個html放到了你身上。
突然你發現, 在國內新聞這個頁面上,有一個連結鏈回“首頁”。作為一隻聰明的蜘蛛,你肯定知道你不用爬回去的吧,因為你已經看過了啊。所以,你需要用你的腦子,存下你已經看過的頁面地址。這樣,每次看到一個可能需要爬的新連結,你就先查查你腦子裡是不是已經去過這個頁面地址。如果去過,那就別去了。
好的,理論上如果所有的頁面可以從initial page達到的話,那麼可以證明你一定可以爬完所有的網頁。
連結:http://www.zhihu.com/question/20899988/answer/24923424
1.爬取一個匿名可訪問upload目錄的網站
import re,os import urllib.request import urllib import ssl ssl._create_default_https_context = ssl._create_unverified_context from collections import deque queue = deque() visited = set() origurl=url = 'http://www.***.cn/Upload/' # 入口頁面, 可以換成別的 path = 'C:/Users/Administrator/Desktop/a/' queue.append(url) cnt = 0 while queue: url = queue.popleft() # 隊首元素出隊 print('已經抓取: ' + str(cnt) + ' 正在抓取 <--- ' + url) cnt += 1 try: urlop = urllib.request.urlopen(url, timeout=3) except: continue if 'image' in urlop.getheader('Content-Type'): xpath=url.replace(origurl,'') orig_list=xpath.split("/") orig_ext_file = orig_list[-1] path_sub = orig_list[:-1] new_path=path+('/'.join(path_sub)) try: os.makedirs(new_path) except Exception as e: print(e) urllib.request.urlretrieve(url, new_path+'/'+orig_ext_file) if 'html' not in urlop.getheader('Content-Type'): continue # 處理異常 try: data = urlop.read().decode('utf-8') except: continue # 正則表達 提取頁面中所有佇列, and判斷or訪問過, too加入待爬佇列 linkre = re.compile('href="(.+?)"') for x in linkre.findall(data): if re.match(r"\?C=.", x): continue if re.match(r"/Upload/", x): continue if x not in visited: queue.append(url + x) visited |= {url} # 標記為已訪問 print('加入佇列 ---> ' + x)
2.抓取一個美圖高清桌布網站
import re import urllib.request import urllib import ssl ssl._create_default_https_context = ssl._create_unverified_context # 取消ssl驗證https:// from collections import deque queue = deque() visited = set() website = 'http://www.***.com/' website_column = 'column/' url = website + website_column + '80827.html' # 入口頁面 path = './images/' queue.append(url) # 加入佇列 cnt = 0 while queue: url = queue.popleft() # 隊首元素出隊 visited |= {url} # 已訪問 print('已經抓取: ' + str(cnt) + ' 正在抓取 <--- ' + url) cnt += 1 try: urlop = urllib.request.urlopen(url, timeout=3) except: continue current_num_re = re.compile(r'/' + website_column + '(\d+)/') current_num = current_num_re.findall(url) if url == website + website_column: continue if 'html' not in urlop.getheader('Content-Type'): continue # 處理異常 try: data = urlop.read().decode('gbk') except: try: data = urlop.read().decode('utf-8') except: continue # 正則表達 提取頁面中所有佇列, and判斷or訪問過, too加入待爬佇列 linkre = re.compile('href="(.+?)"') inside1 = re.compile(r'/' + website_column + '(.*)') inside2 = re.compile(r'(\d+).htm') for x in linkre.findall(data): if 'http' not in x and x not in visited: resulturl = '' c = inside1.findall(x) if c: resulturl = website + website_column + c[0] else: c = inside2.findall(x) if c: cnum = '' cnum = current_num[0] if current_num else '' resulturl = website + website_column + cnum + '/' + c[0] + '.htm' if resulturl: queue.append(resulturl) print('加入佇列 ---> ' + resulturl) linkrerr = re.compile('<p><img src="(.*)" οnlοad="btnaddress\(1\);') src = linkrerr.findall(data) if src: print(src) req = urllib.request.Request(src[0], headers={ 'Connection': 'Keep-Alive', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko', 'Referer': url }) resource = urllib.request.urlopen(req, timeout=30) orig_list = src[0].split("/") orig_ext_file = orig_list[-1] path_sub = orig_list[:-1] # urllib.request.urlretrieve(src[0], path + orig_ext_file) #網站拒絕爬蟲使用Referer 時, urlretrieve無法下載 foo = open(path + orig_ext_file, "wb") str = resource.read() foo.write(str) foo.close()
參考地址: https://jecvay.com/2014/09/python3-web-bug-series1.html