小白爬完文字爬圖片,目標(biāo)百度貼吧洗出。
其實(shí)是偶然的機(jī)會(huì)發(fā)現(xiàn)了這個(gè):
當(dāng)時(shí)就想谭确,為什么創(chuàng)建這個(gè)“旅行吧”呀帘营,從事物發(fā)展的規(guī)律來(lái)說(shuō),就是方便大伙兒各種曬圖各種秀啊!能拿來(lái)曬的東西逐哈,敢情應(yīng)該不會(huì)差到哪去(至少比一般的百度圖片要好一些吧)
好了不多胡扯回歸正題芬迄,幾行代碼,帶足不出戶的你昂秃,走遍萬(wàn)水千山禀梳!
先隨便搜了個(gè)貼,好吧就是這個(gè)了
一械蹋、目標(biāo):
1出皇、獲取帖子標(biāo)題、總頁(yè)數(shù)哗戈、評(píng)論、圖片
2荷科、圖片寫(xiě)入文件并保存
3唯咬、將各種信息實(shí)現(xiàn)打印(測(cè)試追蹤)
4畏浆、輸入帖子號(hào)便能實(shí)現(xiàn)以上操作(亦適用于其它帖子)
二胆胰、步驟:
1、獲取源碼刻获。這個(gè)簡(jiǎn)單蜀涨,用requests的get請(qǐng)求方式即可。這里設(shè)置了random.randint()獲取隨機(jī)數(shù)蝎毡,在一堆范圍中獲取user_agent厚柳,主要是為了偽裝防止網(wǎng)站認(rèn)出是爬蟲(chóng)而限制抓取。至于這一堆user_agents,額沐兵,網(wǎng)上搜的哈哈~
'''
#usr/bin/env python
# -- coding: utf-8 --
def getSource(self,url):
user_agents=['Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20130406 Firefox/23.0','Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0','Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533+ (KHTML, like Gecko) Element Browser 5.0','IBM WebExplorer /v0.94', 'Galaxy/1.0 [en] (Mac OS X 10.5.6; U; en)','Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)','Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14','Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) \Version/6.0 Mobile/10A5355d Safari/8536.25','Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) \Chrome/28.0.1468.0 Safari/537.36','Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; TheWorld)'
index=random.randint(0,9)
user_agent=user_agents[index]
headers = {'User_agent': user_agent}
html=requests.get(url,headers=headers)
return html.text
'''
2别垮、獲取標(biāo)題、總頁(yè)數(shù)扎谎、評(píng)論
主要是匹配正則
標(biāo)題的正則
'''
pattern=re.compile('<h1.*?title.*?>(.*?)</h1>',re.S)
items=re.search(pattern,result)
'''
頁(yè)數(shù)的正則
'''
pattern=re.compile('<h1.*?title.*?>(.*?)</h1>',re.S)
items=re.search(pattern,result)
'''
評(píng)論的正則
'''
pattern=re.compile('<h1.*?title.*?>(.*?)</h1>',re.S)
items=re.search(pattern,result)
'''
3碳想、獲取曬圖
用到BeautifulSoup,首先想到find_all()搜'img'標(biāo)簽烧董,得到如下
龍蛇混雜呀,不僅包括各種旅行曬圖胧奔,還有鏈接中包含'head'的頭像圖逊移,含'emoticon'的表情圖等等,寶寶內(nèi)心是崩潰噠龙填。
如何洗出我們想要的內(nèi)容呢螟左?
別著急,仔細(xì)觀察這些個(gè)鏈接觅够,逐個(gè)點(diǎn)開(kāi)一試就會(huì)發(fā)現(xiàn)胶背,凡是屬于'曬圖'的,接帶有屬性class='BDE_Image'喘先。
我的天钳吟,直接find_all()限定范圍,再循環(huán)打出item['src'],分分鐘搞定鏈接窘拯!要有多簡(jiǎn)單就有簡(jiǎn)單红且,最后將鏈接保存至一個(gè)list中。
4涤姊、創(chuàng)建目錄
用到makedirs()暇番,值得注意的是,如果想將文件夾創(chuàng)建至非系統(tǒng)默認(rèn)的地方思喊,需要用到chdir()來(lái)更改環(huán)境變量壁酬。
5、保存曬圖
萬(wàn)水千山走遍恨课,目錄也創(chuàng)建舆乔,接下來(lái)就是保存圖片。又用到文件操作相關(guān)知識(shí)剂公,千萬(wàn)注意希俩,要想將圖片成功保存至上面創(chuàng)建的目錄,必需指定絕對(duì)路徑纲辽,所以設(shè)置self.path是為了方便此處調(diào)用颜武。
6、集合各操作并獲取多頁(yè)
兩個(gè)循環(huán)拖吼,一個(gè)是多頁(yè)鳞上,一個(gè)是多個(gè)圖片的保存。關(guān)鍵在格式化每一頁(yè)索引鏈接绿贞。
觀察可發(fā)現(xiàn)規(guī)律因块,網(wǎng)頁(yè)URL格式為:'http://tieba.baidu.com/p'+帖子號(hào)+'?pn='+頁(yè)數(shù),所以可以設(shè)置如下:
'''
self.siteURL = 'http://tieba.baidu.com/p/' + str(Num)
self.url=self.siteURL+'?pn='+str(page)
'''
三籍铁、代碼
以上就是基本的思路涡上,接下來(lái)分享代碼趾断,如有錯(cuò)誤還望指正
'''
#usr/bin/env python
# -- coding: utf-8 --
author='WYY'
date='2017.03.14'
#實(shí)戰(zhàn)小項(xiàng)目:百度貼吧爬蟲(chóng)
import urllib2
import requests
import re
import os
import time
import random
from bs4 import BeautifulSoup
#定義一個(gè)Tool()類(lèi)方便清洗數(shù)據(jù)
class Tool():
removeImg = re.compile('<img.*?>|{7}| ') # 去除img標(biāo)簽,1-7位空格吩愧,
removeAddr = re.compile('<a.*?>|</a>') # 刪除超鏈接標(biāo)簽
replaceLine = re.compile('<tr>|<div>|</div>|</p>') # 把換行的標(biāo)簽換位\n
replaceTD = re.compile('<td>') # 把表格制表<td>換為\t
replaceBR = re.compile('<br><br>|<br>|</br>|</br></br>') # 把換行符或者雙換行符換為\n
removeExtraTag = re.compile('.*?') # 把其余標(biāo)簽剔除
removeNoneLine = re.compile('\n+') # 把多余空行刪除
def replace(self, x):
x = re.sub(self.removeImg, "", x)
x = re.sub(self.removeAddr, "", x)
x = re.sub(self.replaceLine, "\n", x)
x = re.sub(self.replaceTD, "\t", x)
x = re.sub(self.replaceBR, "\n", x)
x = re.sub(self.removeExtraTag, "", x)
x = re.sub(self.removeNoneLine, "\n", x)
return x.strip() # 把strip()前后多余內(nèi)容刪除
#定義一個(gè)Spider類(lèi)
class Spider():
#初始化參數(shù)
def __init__(self):
self.tool = Tool()
#獲取源碼
def getSource(self,url):
user_agents=['Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20130406 Firefox/23.0','Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0','Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533+ \(KHTML, like Gecko) Element Browser 5.0','IBM WebExplorer /v0.94', 'Galaxy/1.0 [en] (Mac OS X 10.5.6; U; en)','Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)','Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14','Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) \Version/6.0 Mobile/10A5355d Safari/8536.25','Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) \Chrome/28.0.1468.0 Safari/537.36','Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; TheWorld)']
# user_agent在一堆范圍中隨機(jī)獲取
# random.randint()獲取隨機(jī)數(shù)芋酌,防止網(wǎng)站認(rèn)出是爬蟲(chóng)而訪問(wèn)受限
index=random.randint(0,9)
user_agent=user_agents[index]
headers = {'User_agent': user_agent}
html=requests.get(url,headers=headers)
return html.text
#獲取帖子標(biāo)題
def getTitle(self,url):
result=self.getSource(url)
pattern=re.compile('<h1.*?title.*?>(.*?)</h1>',re.S)
items=re.search(pattern,result)
print u'這篇帖子標(biāo)題為:',self.tool.replace(items.group(1))
#獲取帖子總頁(yè)數(shù)
def getPageNumber(self,url):
result=self.getSource(url)
pattern=re.compile('<ul.*?l_posts_num.*?<span class="red">(.*?)</span>',re.S)
items=re.search(pattern,result).group(1)
print u'帖子共有',items,u'頁(yè)'
return items
#獲取評(píng)論內(nèi)容
def getContent(self,url):
result = self.getSource(url)
pattern=re.compile('<a data-field.*?p_author_name.*?">(.*?)</a>.*?<div id="post_content_.*?>(.*?)</div>',re.S)
items=re.findall(pattern,result)
#獲取樓層數(shù)可以直接用循環(huán),省去正則匹配的麻煩
number = 1
for item in items:
#item[0]為樓主雁佳,item[1]為發(fā)言?xún)?nèi)容脐帝,使用\n換行符打出內(nèi)容更干凈利落
#item[1]中可能有img鏈接,用自定義Tool工具清洗
print u'\n', number, u'樓', u'\n樓主:', item[0], u'\n內(nèi)容:', self.tool.replace(item[1])
time.sleep(0.01)
number += 1
#獲取曬圖,清洗獲得鏈接并保存入list
def getImage(self,url):
result=self.getSource(url)
soup=BeautifulSoup(result,'lxml')
#此處用BeautifulSoup顯然更高效
#find_all()返回一個(gè)list,find()返回一個(gè)元素
#注意class屬性和python內(nèi)置的重合糖权,所以加_變成class_
items=soup.find_all('img',class_="BDE_Image")
images=[]
number=0
for item in items:
print u'發(fā)現(xiàn)一張圖堵腹,鏈接為:',item['src']
images.append(item['src'])
number+=1
if number>=1:
print u'\n',u'共曬圖',number,u'張,厲害了我的哥P前摹>吻辍!'
else:
print u'喏禁偎,沒(méi)有圖......'
return images
#創(chuàng)建目錄
def makeDir(self,path):
self.path=path.strip()
E=os.path.exists(os.path.join('F:\Desktop\code\LvXing', self.path))
if not E:
#創(chuàng)建新目錄,若想將內(nèi)容保存至別的路徑(非系統(tǒng)默認(rèn))腿堤,需要更環(huán)境變量
#更改環(huán)境變量用os.chdir()
os.makedirs(os.path.join('F:\Desktop\code\LvXing', self.path))
os.chdir(os.path.join('F:\Desktop\code\LvXing', self.path))
print u'正在創(chuàng)建名為',self.path,u'的文件夾'
return self.path
else:
print u'名為',self.path,u'的文件夾已經(jīng)存在...'
return False
#萬(wàn)水千山走遍,接下來(lái)就是保存美圖
def saveImage(self,detailURL,name):
data=urllib2.urlopen(detailURL).read()
fileName=name+'.'+'jpg'
#保存文件如暖,一定要用絕對(duì)路徑 `
#所以設(shè)置self.path笆檀,是為了方便后面函數(shù)無(wú)障礙調(diào)用
f=open(r'F:\Desktop\code\LvXing\%s\%s'%(self.path,fileName),'wb')
f.write(data)
f.close()
print u'成功保存圖片',fileName
#集合所有的操作,并獲取多頁(yè)
def getAllPage(self,Num):
self.siteURL = 'http://tieba.baidu.com/p/' + str(Num)
#獲取帖子標(biāo)題
self.getTitle(self.siteURL)
#獲取帖子頁(yè)數(shù)
numbers=self.getPageNumber(self.siteURL)
for page in range(1,int(numbers)+1):
#格式化索引鏈接
self.url=self.siteURL+'?pn='+str(page)
print u'\n\n',u'正準(zhǔn)備獲取第',page,u'頁(yè)的內(nèi)容...'
#獲取評(píng)論
print u'\n',u'正準(zhǔn)備獲取評(píng)論...'
self.getContent(self.url)
#每一頁(yè)創(chuàng)建一個(gè)文件
self.makeDir(path='page'+str(page))
#獲取圖片
print u'\n',u'正準(zhǔn)備獲取圖片...'
images=self.getImage(self.url)
print u'\n',u'正準(zhǔn)備保存圖片...'
number=1
#保存圖片,先從之前的list中找鏈接
for detailURL in images:
name='page'+str(page)+'num'+str(number)
self.saveImage(detailURL,name)
time.sleep(0.1)
number+=1
print u'\n\n',u'完成第',page,u'頁(yè)'
print u'\n\n',u'恭喜盒至,圓滿成功酗洒!'
#raw_input()實(shí)現(xiàn)和外部交互,想看哪個(gè)貼就看哪個(gè)貼
Num=int(raw_input('老哥兒/老妹兒妄迁,輸入帖子號(hào)唄:'))
spider=Spider()
spider.getAllPage(Num)
'''
四寝蹈、結(jié)果
終于寫(xiě)完代碼啦,各種參數(shù)要注意處理好登淘。
然后可以看到如下結(jié)果:
看看文件的變化,圖片已經(jīng)乖乖躺在文件夾中啦
五封字、擴(kuò)展
爬完上面這個(gè)貼黔州,又去胡亂搜尋,發(fā)現(xiàn)兩有趣的貼阔籽。
喜愛(ài)攝影的盆友看過(guò)來(lái)啦~
一個(gè)是:國(guó)外朋友的世界一周旅行記1流妻,Uca姐的攝影好美(獻(xiàn)給所有愛(ài)旅者)
另一個(gè):背起畫(huà)夾去旅行——且行且繪(陸續(xù)更新)
1)、前面這一個(gè)介紹了一個(gè)日本旅行攝影師的世界一周旅行記的故事笆制,照片色彩明麗绅这、利落干凈,迎面滿是異域風(fēng)情在辆。
舉例幾個(gè)圖:
一共100頁(yè)证薇,一頁(yè)也就四五十張圖度苔。。浑度。不過(guò)攝影師的圖還是相當(dāng)?shù)馁澃?/p>
2)另一個(gè)帖子更是好玩寇窑,樓主非常有才,把沿途所見(jiàn)所聞都一一畫(huà)下箩张,畫(huà)風(fēng)那叫一個(gè)清新雅致甩骏,不得不獻(xiàn)上膝蓋。
放幾個(gè)圖感受一下:
其實(shí)還有很多這樣的帖子先慷,隨便輸入帖子號(hào)便玩轉(zhuǎn)貼吧饮笛,幾行代碼走遍萬(wàn)水千山,就是這樣啦~