一杏瞻、介紹
前前后后拖了很久的一個(gè)爬蟲純?cè)瓌?chuàng)我心中的NBA2014-2015賽季現(xiàn)役50大,一般的抓取信息還是蠻簡(jiǎn)單的,但這個(gè)爬蟲在于有些樓層是含圖片的,這樣我們抓取下來(lái)就會(huì)有<img.*?>之類的東西饺藤,很難受;還有就是這個(gè)爬蟲告訴我們當(dāng)正則走投無(wú)路時(shí)BeautifulSoup或許是個(gè)不錯(cuò)的選擇流礁,在匹配數(shù)據(jù)的時(shí)候很好用
二涕俗、流程
- 目標(biāo)站點(diǎn)分析
用瀏覽器打開純?cè)瓌?chuàng)我心中的NBA2014-2015賽季現(xiàn)役50大,開始審查元素崇棠,沒(méi)什么特別的咽袜,很基礎(chǔ)的網(wǎng)頁(yè)結(jié)構(gòu),但在抓取樓層號(hào)和時(shí)間的我們發(fā)現(xiàn)問(wèn)題了——我(艸皿艸 )這讓我怎么寫正則枕稀,還有天理嗎?谜嫉?萎坷?
1.0
2.0
客官莫慌,我們有標(biāo)簽選擇器
標(biāo)簽選擇器的寫法也有很多種沐兰,我這里是參考大鄧的寫法哆档,還蠻好理解的開啟循環(huán),批量抓取
保存數(shù)據(jù)至文本
三住闯、代碼
import requests
from requests.exceptions import RequestException
import re
import json
from bs4 import BeautifulSoup #都是基本的幾個(gè)庫(kù)
def get_one_page(url):
try:
response=requests.get(url)
if response.status_code == 200:
return response.text
return None
except RequestException:
return None
def get_the_number():
a = input("是否只獲取樓主發(fā)言瓜浸,是輸入1,否輸入0:")
a = int(a)
if a == 1 or a == 0:
if a == 1:
print("只看樓主模式>>>")
write_to_file("只看樓主模式>>>")
else:
print('普通模式>>>')
write_to_file("普通模式>>>") #這部分我還是比較滿意的
pattern = re.compile('<h3 class="core_title_txt.*?>(.*?)</h3>.*?'
+'<span class="red".*?>(.*?)</span>.*?<span '
+'class="red">(.*?)</span>.*?</div>', re.S) #為了匹配準(zhǔn)確我把正則寫的不那么“正則”
html=requests.get('https://tieba.baidu.com/p/3138733512?see_lz='+str(a)).text
result=re.search(pattern,str(html))
if result:
print('標(biāo)題:', result.group(1))
print('回復(fù)數(shù):',result.group(2))
b= result.group(3)
print('頁(yè)數(shù):',b)
else:
print('獲取頁(yè)數(shù)信息失敗')
return a,b #return多個(gè)對(duì)象比原,沒(méi)毛病
def get_the_floor_time(html): #把樓層號(hào)和時(shí)間的信息搞出來(lái)
soup = BeautifulSoup(html, 'lxml')
items=soup.find_all('span',{'class':'tail-info'}) #嗯插佛,這里就用標(biāo)簽選擇器來(lái)選擇樓層號(hào)和時(shí)間
pattern = re.compile('<span class="tail-info">(\d.*?)</span>', re.S) #再用正則匹配,這個(gè)時(shí)候一定要細(xì)心量窘,一開始我寫的是'<span class="tail-info">(\d.*?)</span>雇寇,'結(jié)果最后一個(gè)日期就匹配不到,具體原因看items蚌铜,仔細(xì)看锨侯!
items = re.findall(pattern, str(items))
return items #這里得到的items是一個(gè)列表,返回它就好冬殃,之后再輸出
def get_the_content(html): #輸出帖子的樓層內(nèi)容并且把<img....>之類的刪了
soup = BeautifulSoup(html, 'lxml')
contents=soup.find_all('div',{'class':'d_post_content j_d_post_content '})
if contents:
items=get_the_floor_time(html)
i=-1
for content in contents:
content=content.get_text().strip() #得到樓層內(nèi)容的純文本
i=i+1
print(items[2 * i])
write_to_file(items[2 * i]) #寫入數(shù)據(jù)
print(items[2 * i + 1])
write_to_file(items[2 * i + 1])
print(content)
write_to_file(content)
print('----------------------------------------------------------------------------------------------------')
write_to_file('-------------------------------------------------------------------------------------------')
else:
print("獲取帖子內(nèi)容失敗")
def write_to_file(content): #這基本是標(biāo)配了
with open('bdtb_result.text','a',encoding='utf-8') as f:
f.write(json.dumps(content,ensure_ascii=False)+'\n')
f.close()
def main():
c = get_the_number() #得到的是get_the_number()的返回值囚痴,一個(gè)列表
a=(c[0])
b=int(c[1]) #這里要int,b代表的是頁(yè)數(shù)审葬,得到b深滚,我們就知道要循環(huán)多少次了
for b in range(1,b+1):
url = 'https://tieba.baidu.com/p/3138733512?see_lz='+str(a)+'&pn='+str(b)
get_one_page(url)
html=get_one_page(url)
get_the_content(html)
if __name__=='__main__':
main()
四骂束、最后得到的數(shù)據(jù)視圖和文件
3.0
五、總結(jié)
1.要好好利用工具成箫,遇到問(wèn)題多問(wèn)度娘
2.在這里最初的想法是把每個(gè)樓層的用戶名也打印出來(lái)的展箱,運(yùn)行到300多層的時(shí)候總是報(bào)錯(cuò),等我找到好的解決辦法再po上來(lái)
3.未完待續(xù).....