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
結果輸出如下
2、正則比對
打開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頁,要分情況讨論。
最後來看抓取的結果:
四、奉上源碼
#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('請輸入結束頁數))