天天看點

python網絡爬蟲入門(一)——糗事百科熱門帖

python小白,剛學習爬蟲不久,會一般的靜态網頁抓取,動手來寫第一個例子。

一、目标

    1、抓取糗事百科熱門帖,擷取其釋出者、評論、點贊數、評論等資訊

    2、将資訊清洗并列印,循環輸出

    3、設計程式,使可以選擇抓取的頁面範圍 

    4、将每一頁的資訊儲存到文本

二、開發環境介紹

phthon 2.7.13

IDE:PyCharm

采用庫:re、requests、time

三、步驟

    1、擷取源碼

首先用requests庫的get方法擷取首頁源代碼

user_agent = 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36'
headers={'User_agent': user_agent}
r=requests.get(url,headers=headers)
result=r.text
print result
           

結果輸出如下

python網絡爬蟲入門(一)——糗事百科熱門帖

2、正則比對

python網絡爬蟲入門(一)——糗事百科熱門帖

打開360浏覽器,右鍵點選審查元素,可以清晰的看到釋出者、年齡、釋出内容、評論數等的分布及标簽構造,根據各種關鍵詞可以比對正則設定循環,列印輸出

pattern=re.compile('<div class="author.*?<h2>(.*?)</h2>.*?Icon">(.*?)</div>.*?<div class="content">.*?<span>(.*?)</span>.*?<span.*?stats-vote.*?number">(.*?)</i>.*?stats-comments.*?number">(.*?)</i>.*?up.*?number hidden">(.*?)</span>.*?down.*?number hidden">(.*?)</span>',re.S)
items=re.findall(pattern,result)
 	number=1
        for item in items:
            print u''
            print number,u'樓',u'\n樓主:',item[0],u'',item[1],u'歲',u'\n發言:',self.tool.replace(item[2]),u'\n好笑:',item[3],u'\n評論:',item[4],u'\n贊:',item[5],u'\n踩:',item[6]
            time.sleep(0.1)
            number+=1
           

3、 面向對象

#定義一個Spider類
class Spider(object):
    #初始化參數
    def __init__(self):
        self.siteURL ='http://www.qiushibaike.com/'
        self.tool=Tool()

    #擷取網頁源碼
    def getSource(self,url):
        user_agent = 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36'
        headers = {'User_agent': user_agent}
        r=requests.get(url,headers=headers)
        result=r.text
        return result

    #擷取詳情頁資訊,并循環列印輸出
    def getDetailPage(self,detailURL):
        source=self.getSource(detailURL)
        pattern=re.compile('<div class="author.*?<h2>(.*?)</h2>.*?Icon">(.*?)</div>.*?<div class="content">.*?<span>(.*?)</span>.*?<span.*?stats-vote.*?number">(.*?)</i>.*?stats-comments.*?number">(.*?)</i>.*?up.*?number hidden">(.*?)</span>.*?down.*?number hidden">(.*?)</span>',re.S)
        items=re.findall(pattern,source)
        number=1
        for item in items:
            print u''
            print number,u'樓',u'\n樓主:',item[0],u'',item[1],u'歲',u'\n發言:',self.tool.replace(item[2]),u'\n好笑:',item[3],u'\n評論:',item[4],u'\n贊:',item[5],u'\n踩:',item[6]
            time.sleep(0.1)
            number+=1
        return items

           

4、資料清洗

可以看到所得代碼中含較多的</br><br><br />等标簽,可以定義一個Tool類進行清洗

class Tool():
    def replace(self,x):
        x=re.sub(re.compile('<br>|</br>|/>|<br'),"",x)
        return x.strip()
           

5、文本儲存

定義一個saveDetailPage函數,傳入檔案名和資料,在此不贅述

  6、擷取多頁

上面的内容我們已經成功用正規表達式比對出想要的内容,想擷取多頁,隻需設定一個循環即可

是以關鍵内容來啦!

觀察底面标簽可知熱門評論共35頁,觀察網頁位址欄可發現規律:

首頁 url即'http://www.qiushibaike.com/',從第二頁開始為 url+/8hr/page/x/?s=4964698  ,可以推測:8hr為8小時内最熱門,x即頁數,後面s=4964698,部落客猜測是通路該網站的總次數,因為如果在同一個會話中,s是相同的,反之另外打開通路時s又不同,且每次發現s有增加!

由以上分析,我們要周遊這35頁,要分情況讨論。

最後來看抓取的結果:

python網絡爬蟲入門(一)——糗事百科熱門帖
python網絡爬蟲入門(一)——糗事百科熱門帖
python網絡爬蟲入門(一)——糗事百科熱門帖

四、奉上源碼

#usr/bin/env python
# -*- coding: utf-8 -*-

import re
import requests
import time


#定義一個Tool類,友善用replace方法把換行符等删除
class Tool():
    def replace(self,x):
        x=re.sub(re.compile('<br>|</br>|/>|<br'),"",x)
        return x.strip()


#定義一個Spider類
class Spider(object):
    #初始化參數
    def __init__(self):
        self.siteURL ='http://www.qiushibaike.com/'
        self.tool=Tool()

    #擷取網頁源碼
    def getSource(self,url):
        user_agent = 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36'
        headers = {'User_agent': user_agent}
        r=requests.get(url,headers=headers)
        result=r.text
        return result

    #擷取詳情頁資訊,并循環列印輸出
    def getDetailPage(self,detailURL):
        source=self.getSource(detailURL)
        pattern=re.compile('<div class="author.*?<h2>(.*?)</h2>.*?Icon">(.*?)</div>.*?<div class="content">.*?<span>(.*?)</span>.*?<span.*?stats-vote.*?number">(.*?)</i>.*?stats-comments.*?number">(.*?)</i>.*?up.*?number hidden">(.*?)</span>.*?down.*?number hidden">(.*?)</span>',re.S)
        items=re.findall(pattern,source)
        number=1
        for item in items:
            print u''
            print number,u'樓',u'\n樓主:',item[0],u'',item[1],u'歲',u'\n發言:',self.tool.replace(item[2]),u'\n好笑:',item[3],u'\n評論:',item[4],u'\n贊:',item[5],u'\n踩:',item[6]
            time.sleep(0.1)
            number+=1
        return items

    #儲存資訊寫入檔案
    def saveDetailPage(self,data,name):
        fileName='page'+name+'.'+'txt'
        f=open(fileName,'wb')
        f.write(data.encode('utf-8'))
        print u'',u'成功将資料儲存入檔案',fileName
        f.close()

    #對一頁的操作
    def OnePage(self,detailURL,name):
        data=self.getDetailPage(detailURL)
        self.saveDetailPage(str(data),str(name))

    #對很多頁的操作
    #分兩種情況讨論,start頁等于1\start頁大于1
    def getAllPage(self,start,end):
        if start==1:
            print u'正在擷取第1頁的資料...'
            detailURL=self.siteURL
            self.OnePage(detailURL,start)
            number=2
            for page in range(2, end+1):
                print u'正在擷取第', number, u'頁的資料...'
                detailURL = self.siteURL + '8hr/page/' + str(page) + '/?s=4964625'
                self.OnePage(detailURL,number)
                time.sleep(2)
                number +=1
            if number==end+1:
                print u'',u'\n加載結束!'
                return False

        elif start>1:
            number=start
            for page in range(start,end+1):
                print u'',u'\n正在擷取第',number,u'頁的資料...'
                detailURL=self.siteURL + '8hr/page/' +str(page)+ '/?s=4964625'
                self.OnePage(detailURL,number)
                time.sleep(2)
                number += 1
            if number==end+1:
                print u'',u'加載結束!'
                return False

spider=Spider()
spider.getAllPage(start=int(raw_input('請輸入起始頁數:')),end=int(raw_input('請輸入結束頁數))