上一篇簡單的實現了獲取url返回的內容,在這一篇就要第返回的內容進行提取,並將結果儲存到html中。
一 、 需求:
抓取主頁面:百度百科Python詞條 https://baike.baidu.com/item/Python/407313
分析上面的原始碼格式,便於提取:
- 關鍵詞分析:位於class為lemmaWgt-lemmaTitle-title的dd元素的第一個h1標籤內
- 簡介分析(位於class為lemma-summary的div的text內容)
- 其他相關聯的標籤的分析(是a標籤,且href以/item/開頭)
二、抓取過程流程圖:

三、分析:
1. 網頁下載器:
1.作用:
將網際網路上URL對應的網頁以HTML形式下載到本地
常用的本地下載器
1、urllib2 Python官方基礎模組
2、requests 第三方包,功能更強大
2.urllib下載網頁的三種方法
(1)URL傳入urllib2.urlopen(url)方法
import urllib2 #直接請求 response = urllib2.urlopen('http://www.baidu.com') #獲取狀態碼,如果是200表示成功 code = response.getcode() #讀取內容 cont = response.read()
(2)新增data、http header
將url、data、header傳入urllib.Request方法
然後 URLlib.urlopen(request)
import urllib2 #建立Request物件 request = urllin2.Request(url) #新增資料 request.add_data('a'.'1') #新增http的header 將爬蟲程式偽裝成Mozilla瀏覽器 request.add_header('User-Agent','Mozilla/5.0') #傳送請求獲取結果 response = urllib2.urlopen(request)
(3)新增特殊情景的處理器
處理使用者登入才能訪問的情況,新增Cookie
或者需要代理才能訪問 使用ProxyHandler
或者需要使用https請求
2.網頁解析器
1.作用:
從網頁中提取有價值資料的工具
以HTML網頁字串為輸入資訊,輸出有價值的資料和新的待爬取url列表
網頁解析器種類
1、正規表示式 將下載好的HTML字串用正規表示式匹配解析,適用於簡單的網頁解析 字串形式的模糊匹配
2、html.parser python自帶模組
3、BeautifulSoup 第三方外掛
4、xml 第三方外掛
原理是解析成DOM樹:
2.BeautifulSoup簡介及使用方法:
1.簡介:
BeautifulSoup:Python第三方庫,用於從HTML或XML中提取資料
安裝並測試beautifulsoup
方法1:-安裝:pip install beautifulsoup4
-測試:import bs4
方法2:pycharm--File--settings--Project Interpreter--新增beautifulsoup4
2.語法介紹:
根據HTML網頁字串可以建立BeautifulSoup物件,建立好之後已經載入完DOM樹
即可進行節點搜尋:find_all、find。搜尋出所有/第一個滿足要求的節點(可按照節點名稱、屬性、文字進行搜尋)
得到節點之後可以訪問節點名稱、屬性、文字
如:
<a href="123.html" class="aaa">Python</a>
可根據:
節點名稱:a
節點屬性:href="123.html" class="aaa"
節點內容:Python
建立BeautifulSoup物件:
from bs4 import BeautifulSoup
#根據下載好的HTML網頁字串建立BeautifulSoup物件
soup = BeautifulSoup(
html_doc, #HTML文件字串
'html.parser' #HTML解析器
from_encoding='utf-8' #HTML文件編碼
)
搜尋節點:
方法:find_all(name,attrs,string)
#查詢所有標籤為a的節點
soup.find_all('a')
#查詢所有標籤為a,連結符合/view/123.html形式的節點
soup.find_all('a',href='/view/123.html')
soup.find('a',href=re.compile('aaa')) #用正規表示式匹配內容
#查詢所有標籤為div,class為abc,文字為Python的節點
soup.find_all('div',class_='abc',string='Python') #class是Python關鍵字 避免衝突
由於class是python的關鍵字,所以講class屬性加了個下劃線。
訪問節點資訊:
得到節點:<a href="123.html" class="aaa">Python</a>
#獲取查詢到的節點的標籤名稱
node.name
#獲取查詢到的節點的href屬性
node['href']
#獲取查詢到的節點的連線文字
node.gettext()
四、程式碼實現:
spider.py
# 爬蟲的入口排程器 from baike import url_manager, html_downloader, html_parser, html_outputer class SpiderMain(object): def __init__(self): self.urlManager = url_manager.UrlManager() self.downloader = html_downloader.HtmlDownLoader() self.parser = html_parser.HtmpParser() self.outputer = html_outputer.HtmlOutpter() def craw(self,url): count = 1 #定義爬取幾個頁面 self.urlManager.add_new_url(url) while self.urlManager.has_new_url(): try: # 獲取一個url new_url = self.urlManager.get_new_url() # 訪問url,獲取網站返回資料 html_content = self.downloader.download(new_url) new_urls, new_datas = self.parser.parse(new_url, html_content) self.urlManager.add_new_urls(new_urls) self.outputer.collect_data(new_datas) print(count) if count == 5: break count = count+1 except Exception as e: print("發生錯誤",e) # 將爬取結果輸出到html self.outputer.out_html() if __name__=="__main__": url = 'https://baike.baidu.com/item/Python/407313' sm = SpiderMain() sm.craw(url)
url_manager.py
# url管理器 class UrlManager(object): def __init__(self): # 定義兩個set,一個存放未爬取的url,一個爬取已經訪問過的url self.new_urls = set() self.old_urls = set() # 新增一個url的方法 def add_new_url(self,url): if url is None: return None if url not in self.new_urls and url not in self.old_urls: self.new_urls.add(url) # 判斷是否還有待爬取的url(根據new_urls的長度判斷是否有待爬取的頁面) def has_new_url(self): return len(self.new_urls) != 0 # 定義獲取一個新的url的方法 def get_new_url(self): if len(self.new_urls)>0: # 從new_urls彈出一個並新增到old_urls中 new_url = self.new_urls.pop() self.old_urls.add(new_url) return new_url # 批量新增url的方法 def add_new_urls(self, new_urls): if new_urls is None: return for url in new_urls: self.add_new_url(url)
html_downloader.py
# 讀取網頁的類 import urllib.request class HtmlDownLoader(object): def download(self, url): if url is None: return # 訪問url response = urllib.request.urlopen(url) # 如果返回的狀態碼不是200代表異常 if response.getcode() != 200: return return response.read()
html_parser.py
# 網頁解析器類 import re import urllib from bs4 import BeautifulSoup class HtmpParser(object): # 解析讀取到的網頁的方法 def parse(self, new_url, html_content): if html_content is None: return soup = BeautifulSoup(html_content,'html.parser',from_encoding='utf-8') new_urls = self.get_new_urls(new_url,soup) new_datas = self.get_new_datas(new_url,soup) return new_urls, new_datas # 獲取new_urls的方法 def get_new_urls(self, new_url, soup): new_urls = set() # 查詢網頁的a標籤,而且href包含/item links = soup.find_all('a',href=re.compile(r'/item')) for link in links: # 獲取到a必去哦啊Ian的href屬性 url = link['href'] # 合併url。使爬到的路徑變為全路徑,http://....的格式 new_full_url = urllib.parse.urljoin(new_url,url) new_urls.add(new_full_url) return new_urls # 獲取new_data的方法 def get_new_datas(self, new_url, soup): new_datas = {} # 獲取標題內容 title_node = soup.find('dd',class_='lemmaWgt-lemmaTitle-title').find('h1') new_datas['title'] = title_node.get_text() #獲取簡介內容 summary_node = soup.find('div',class_='lemma-summary') new_datas['summary'] = summary_node.get_text() new_datas['url'] = new_url return new_datas
html_outputer.py
# 爬蟲的入口排程器 from baike import url_manager, html_downloader, html_parser, html_outputer class SpiderMain(object): def __init__(self): self.urlManager = url_manager.UrlManager() self.downloader = html_downloader.HtmlDownLoader() self.parser = html_parser.HtmpParser() self.outputer = html_outputer.HtmlOutpter() def craw(self,url): count = 1 #定義爬取幾個頁面 self.urlManager.add_new_url(url) while self.urlManager.has_new_url(): try: # 獲取一個url new_url = self.urlManager.get_new_url() # 訪問url,獲取網站返回資料 html_content = self.downloader.download(new_url) new_urls, new_datas = self.parser.parse(new_url, html_content) self.urlManager.add_new_urls(new_urls) self.outputer.collect_data(new_datas) print(count) if count == 5: break count = count+1 except Exception as e: print("發生錯誤",e) # 將爬取結果輸出到html self.outputer.out_html() if __name__=="__main__": url = 'https://baike.baidu.com/item/Python/407313' sm = SpiderMain() sm.craw(url)
執行spider.py的主函式:(結果會將提取到的結果儲存到html中)
總結:
python的類類似於java,繼承object
python的返回值return和return None一樣(None類似於java的null關鍵字)
下面附上自己基於java實現此爬蟲的地址: