功能:從初始網址爬取並抽取內層網址繼續爬取
技術:隨機User-Agent生成,隊列,多線程,robots解析,下載限流,mongodb存儲,爬取深度限制,重試下載,抽取特定路由,真正下載,網址正常化,功能封裝
規範:用到類屬性和類方法的方法在類裏編寫,用不到的在類外面編寫,能夠建個助手目錄utils存放這些助手函數html
一般在開發過程當中不可能一會兒就把init寫得完整,先把最易用到的,已經想到的初始化,後面的在編寫其餘函數想到時再來init裏編寫mongodb
使用不一樣的隊列會形成BFS和DFS的效果 使用先進先出隊列產生廣度優先搜索,使用先進後出(棧)產生深度優先搜索多線程
text:返回的是unicode 型的數據,通常是在網頁的header中定義的編碼形式,若是想要提取文本就用text;
content:返回的是bytes,二級制型的數據;想要提取圖片、文件,就要用到content;
.text是現成的字符串,.content還要編碼,可是.text不是全部時候顯示都正常,這是就須要用.content進行手動編碼。dom
將重試下載模塊封裝在此,不對用戶展現重試下載接口函數
保存函數:將爬取內容MD5加密存儲到文件中,注:使用mongodb保存結果則無需次函數工具
方式:lxml、BeautifulSoup、正則網站
lxml編碼
1 html = lxml.html.fromstring(html_content) 2 html_data = html.xpath('//a/@href')
BeautifulSoup加密
1 soup = BeautifulSoup('lxml') 2 a_list = soup.find_all('a') 3 for a in a_list: 4 print(a['href'])
正則url
1 url_regex = re.compile('<a[^>]+href=["\'](.*?)["\']', re.IGNORECASE) 2 return url_regex.findall(html_content.decode("utf-8"))
decode解碼問題:不一樣網站所使用的編碼方式有所不一樣—— utf-8 , gbk, gb2312, ISO-8859-1
實現一個類方法的時候,要注意類方法是否使用了當前類的屬性或其餘方法,若是未使用就說明和當前類沒有直接關係,最好獨立出來,當作工具方法
1 urljoin:拼接網址,若參數2網址是正確格式,那麼拼接的結果只是參數2網址,參數1網址忽略;若參數2網址是錯誤格式或是後綴path,那麼和參數1網址進行拼接 2 urljoin('http://www.baidu.com','/ljb.html/index.html') 3 'http://www.baidu.com/ljb.html/index.html' 4 5 urljoin('http://www.baidu.com','http://ljb.html/index.html') 6 'http://ljb.html/index.html' 7 8 urljoin('/www.baidu.com','http://ljb.html/index.html') 9 'http://ljb.html/index.html' 10 11 urljoin('/test.html','http://ljb.html/index.html') 12 'http://ljb.html/index.html' 13 14 urljoin('http://www.baidu.com/test.html','http://ljb.html/index.html') 15 'http://ljb.html/index.html' 16 17 urljoin('http://www.baidu.com/test.html','http://www.sina.com/ljb.html/index.html') 18 'http://www.sina.com/ljb.html/index.html'
限流:設置爬取的間隔時間是爲了不IP被封鎖,隨機間隔時間更可靠
原理:以delay做爲時間間隔或超過delay纔可進行訪問(爬取)
第一次訪問:獲取不到網址對應的訪問時間(不執行if-else語句),以網址地址爲鍵,訪問時間爲值存入字典
第二次訪問:獲取上次訪問對應網址的訪問時間,進行if-else判斷,計算時間差
注:若delay>(此次訪問時間-上次訪問時間),說明還沒等夠,還須要繼續等待,還需等待的時間是——總等待時間delay減去已經等待的時間(就是當前時間減去本次訪問的時間)
注:若delay<(此次訪問時間-上次訪問時間),說明已經等夠了,能夠直接訪問
1 urlparse('http://www.baidu.com/index.html?x=123&y=789#13579') 2 ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='', query='x=123&y=789', fragment='13579')