編寫爬蟲的一些感想(就是高興)

今天,根據網頁的結構,嘗試了下如何抓取煎蛋首頁上的文章。目標很簡單: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

1. 爬蟲前的準備

我這裏使用了Python中的如下模塊:網絡

  • beautifulsoup:第三方模塊,用於解析網頁內容。併發

  • requests:第三方模塊,用於獲取網頁內容。app

  • re:內置模塊,用於編寫正則表達式

  • codecs:內置模塊,用於操做文件

這即是所有準備了。在這裏要多嘴一句,包括re模塊在內都存在替代品,若是須要能夠根據本身的喜愛來選擇。

2. 分析程序邏輯

在編寫代碼以前,要分析如何抓取並處理網頁。以抓取一篇文章鯨魚有鯨語,鯨語有口音爲例。咱們要實現:

  • 下載網頁,獲取數據——源代碼或者json數據

  • 解析數據,從數據中抽出咱們須要的內容——這裏是文章標題和文章內容(只有文字)

  • 整理數據,將解析好的數據寫入文件中。

這樣,能夠根據實現的內容,將代碼分爲三個部分,用函數來整合:

  • download_page(url):接受一個URL(一般是網址),下載網頁,然後獲取數據(固然,不止下載網頁而已,還有不少內容,但對於如今來講,這麼講就好)

  • parse_article(data):接受上面的函數返回的data,並解析爲咱們須要的內容

  • write_article(title, content):接受上面的函數返回的標題和文章內容,並寫入文件中。

這三個部分中,如今我感受最難的是其中的parse_article(data)。固然,一部分是由於個人經驗不足,常常要花很長時間才找到須要的內容。這裏,推薦讀者在瀏覽器中使用右鍵——查找元素來輔助解析網頁。

當明白怎麼爬取一篇文章的時候,爬取其餘內容就是一些細節上的事情了。細節上的內容能夠經過模塊的文檔來獲取。我提到的兩個第三方模塊的中文資料都比較豐富(百度一下便可),因此再也不贅述。這裏只說明幾個須要注意下的細節:

  1. 在發送請求的時候,網頁可能會經過檢查頭信息中的User-Agent來判斷是不是一我的瀏覽網頁。最簡單的解決問題的方法就是本身寫一個頭信息,假裝成一我的。

  2. 若是抓取的頻率過快,可能會被服務器拒絕訪問,若是IP被封了就完了。這裏有兩個解決問題的思路:

    • 使用IP代理,輪換IP訪問網頁

    • 設置一個簡單的爬蟲測試服務器能夠接受的訪問頻率,從慢而快的訪問網頁。(就是看服務器的忍受程度是多少)

  3. 網頁上一般不止有一個地方包含了咱們所需的內容(好比有兩個塊能夠實現下一頁的功能),因此,一個塊難解析可使用另外一個塊,變通下嘛~

3. 爬蟲實例

這裏以抓取一篇文章鯨魚有鯨語,鯨語有口音爲例。剛纔提到了,要實現三個函數:

  • download_page(url)

  • parse_article(data)

  • write_article(title, content)

3.1 下載數據

首先是第一個函數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權威指南的一部分),就能夠明白這裏是什麼意思啦~

3.2 解析數據

下面是第二個函數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
    # 返回標題和參數,用於寫入文件。

3.3 整理數據

獲取咱們須要的全部數據(標題和內容)之後,須要將其寫入文件中。咱們首先須要拼接一個文件名,建立並打開文件。這裏要注意參數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)

4. 文章結束前的一些話

嗯,本文到這裏就結束了。下面還有抓取簡單首頁文章的爬蟲。不過爬取的過程也是上面的幾步,若是看懂的話,就能夠編寫出來。看不懂的話……嗯,其實我只是由於開心想炫耀一下,哈哈哈哈來打我啊~~


我是胡一波,集帥氣與智慧於一身的美男子,天天都被本身帥醒。若是各位發現這些代碼有問題的話,請跟我說,我會盡快回復併發送一塊錢!這些錢能夠指定給任意人或者機構(好比慈善組織和開源項目),就醬~

相關文章
相關標籤/搜索