今天,根據網頁的結構,嘗試了下如何抓取煎蛋首頁上的文章。目標很簡單:html
根據首頁上面的文章連接,載入文章,然後將文章的標題和正文(不帶圖片)抓取下來。python
抓取首頁上面文章的連接,標題,做者和所屬標籤。正則表達式
按標題將文章寫入一個.txt
格式的文件json
將首頁上抓取的內容整合起來,製做成格式以下的Markdown
簡介。瀏覽器
首頁的簡介格式以下:服務器
**文章標題**:鯨魚有鯨語,鯨語有口音 **文章連接**:[http://jandan.net/2016/02/18/caribbean-whales.html](http://jandan.net/2016/02/18/caribbean-whales.html) **譯者**:Cedric **標籤**:走進科學 ...
如此反覆便可。這裏要說明下,因爲煎蛋首頁和餘下頁碼的網頁結構不一樣,我沒有再寫餘下頁面的簡介。若是有人有興趣的話,能夠編寫則個~下面,我會說明在編寫爬蟲過程當中的所思所想。markdown
我這裏使用了Python中的如下模塊:網絡
beautifulsoup
:第三方模塊,用於解析網頁內容。併發
requests
:第三方模塊,用於獲取網頁內容。app
re
:內置模塊,用於編寫正則表達式
codecs
:內置模塊,用於操做文件
這即是所有準備了。在這裏要多嘴一句,包括re
模塊在內都存在替代品,若是須要能夠根據本身的喜愛來選擇。
在編寫代碼以前,要分析如何抓取並處理網頁。以抓取一篇文章鯨魚有鯨語,鯨語有口音爲例。咱們要實現:
下載網頁,獲取數據——源代碼或者json
數據
解析數據,從數據中抽出咱們須要的內容——這裏是文章標題和文章內容(只有文字)
整理數據,將解析好的數據寫入文件中。
這樣,能夠根據實現的內容,將代碼分爲三個部分,用函數來整合:
download_page(url)
:接受一個URL(一般是網址),下載網頁,然後獲取數據(固然,不止下載網頁而已,還有不少內容,但對於如今來講,這麼講就好)
parse_article(data)
:接受上面的函數返回的data
,並解析爲咱們須要的內容
write_article(title, content)
:接受上面的函數返回的標題和文章內容,並寫入文件中。
這三個部分中,如今我感受最難的是其中的parse_article(data)
。固然,一部分是由於個人經驗不足,常常要花很長時間才找到須要的內容。這裏,推薦讀者在瀏覽器中使用右鍵——查找元素
來輔助解析網頁。
當明白怎麼爬取一篇文章的時候,爬取其餘內容就是一些細節上的事情了。細節上的內容能夠經過模塊的文檔來獲取。我提到的兩個第三方模塊的中文資料都比較豐富(百度一下便可),因此再也不贅述。這裏只說明幾個須要注意下的細節:
在發送請求的時候,網頁可能會經過檢查頭信息中的User-Agent
來判斷是不是一我的瀏覽網頁。最簡單的解決問題的方法就是本身寫一個頭信息,假裝成一我的。
若是抓取的頻率過快,可能會被服務器拒絕訪問,若是IP被封了就完了。這裏有兩個解決問題的思路:
使用IP代理,輪換IP訪問網頁
設置一個簡單的爬蟲測試服務器能夠接受的訪問頻率,從慢而快的訪問網頁。(就是看服務器的忍受程度是多少)
網頁上一般不止有一個地方包含了咱們所需的內容(好比有兩個塊能夠實現下一頁的功能),因此,一個塊難解析可使用另外一個塊,變通下嘛~
這裏以抓取一篇文章鯨魚有鯨語,鯨語有口音爲例。剛纔提到了,要實現三個函數:
download_page(url)
parse_article(data)
write_article(title, content)
首先是第一個函數download_page(url)
。因爲內容單一,因此實現比較簡單(要注意的是,這裏須要準備一些防反爬蟲的措施)。下面將展現如何假裝成一個瀏覽器下載網頁或者其中的數據:
def download_page(url): headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) ' 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36' } data = requests.get(url, headers=headers).content return data
咱們這裏假裝了一個火狐瀏覽器。這個信息不須要你輸入或者從這裏複製,若是須要的話,能夠在瀏覽器中右鍵——查看元素——網絡
然後就能夠查看消息頭並假裝成你本身的瀏覽器了。咱們這裏使用的HTTP請求中的get
方法,若是有看過以前的內容(指HTTP權威指南的一部分),就能夠明白這裏是什麼意思啦~
下面是第二個函數parse_article(data)
,內容比較複雜,並且是根據咱們要爬取的文章頁面制定的。咱們首先放到文章的主體上,右鍵——查看元素
,能夠看到主體的部分結構是這樣的:
嗯,能夠明白(若是不明白的話,請本身補習HTML的基礎知識。這部分在Segmantfault裏面蒐集便可)文章的主體部分在<div class="post f">
中。其中,標題在其中的<h1>
標籤的文本內部,而正文則是其中的<p>
標籤的內容。
據此,咱們可使用beatifulsoup
來實現咱們的第二個函數:
def parse_article(html): soup = BeautifulSoup(html, 'html.parser') # 從上面的數據獲取html文檔並解析,這裏使用的是Python自帶的HTML解釋器 article = soup.find('div', attrs={'class': 'post f'}) # 縮小HTML文檔的解析範圍,限定在文章主體內部。 title = article.find('h1').getText() # 獲取文章主體內部的<h1>標籤內的文本,能夠發現這就是標題內容。 paras = [] # 建立一個列表,以段落的形式,向裏面填充文本。 for paragraph in article.find_all('p'): p_content = paragraph.getText() # 獲取<p>標籤內的文本,這裏就是段落文本內容。 paras.append(p_content) return title, paras # 返回標題和參數,用於寫入文件。
獲取咱們須要的全部數據(標題和內容)之後,須要將其寫入文件中。咱們首先須要拼接一個文件名,建立並打開文件。這裏要注意參數wb
。在Python3.X中,b
參數是自動添加的(若是沒有寫則會填上去,有的話就不會本身填上去);可是在Python2.X中不是這樣,因此最好填上去,避免換了版本之後出現一些奇怪的Bug。固然,不換也行~
def get_article(title, url): file_name = title + '.txt' # 拼接文件名 with codecs.open(file_name, 'wb', encoding='utf-8') as fp: html = download_page(url) # 調用第一個函數獲取數據 title2, text = parse_article(html) # 調用第二個函數獲取數據 fp.write('\t%s\t\r\n' % title2) for p in text: fp.write('\t%s\r\n' % p) # 將獲取的數據寫入文件。 print('文章讀取完畢!') return 'OK'
最後,還要再編寫一個if
語句,判斷是運行仍是導入。運行文件的時候,能夠經過調用第三個函數來實現咱們的目的。
if __name__ == '__main__': url = 'http://jandan.net/2016/02/18/caribbean-whales.html' get_article(url)
嗯,本文到這裏就結束了。下面還有抓取簡單首頁文章的爬蟲。不過爬取的過程也是上面的幾步,若是看懂的話,就能夠編寫出來。看不懂的話……嗯,其實我只是由於開心想炫耀一下,哈哈哈哈來打我啊~~
我是胡一波,集帥氣與智慧於一身的美男子,天天都被本身帥醒。若是各位發現這些代碼有問題的話,請跟我說,我會盡快回復併發送一塊錢!這些錢能夠指定給任意人或者機構(好比慈善組織和開源項目),就醬~