升級(jí)裝備棺榔,讓你的小爬蟲變得更能干
在上一篇文章中我們講到了如何用requests對(duì)網(wǎng)頁進(jìn)行GET和POST請(qǐng)求询吴,以及用BeautifulSoup對(duì)請(qǐng)求到的頁面進(jìn)行分析。但是單單這樣哨苛,小爬蟲只能對(duì)單一的頁面進(jìn)行爬取己莺,還并不能完全解放我們的人力,只能算是個(gè)半自動(dòng)的爬蟲尖飞,那么這篇文章中症副,我們要給這只小爬蟲再升級(jí)幾件厲害的裝備,讓它變得更能干政基!
任務(wù)目標(biāo)
首先贞铣,我們面前有一份長長的Excel表格,里面提供了文章的案例編號(hào)沮明,需要爬蟲根據(jù)這份表格里面的案例編號(hào)辕坝,來進(jìn)行相對(duì)應(yīng)文章的爬取。其次荐健,我們還需要對(duì)每篇文章爬取的內(nèi)容做保存酱畅,不然關(guān)掉IDE后琳袄,數(shù)據(jù)就全部丟失了。
根據(jù)這份需求纺酸,我們需要給這只小爬蟲裝備上2件裝備
- 對(duì)Excel文件的操作
- 對(duì)文件進(jìn)行讀取和寫入操作
裝備一:對(duì)Excel文件的讀取操作
第一步還是需要邀請(qǐng)pip
來配合窖逗,通過pip
來自動(dòng)安裝xlrd
模塊。
pip install xlrd
這兒解釋下餐蔬,xlrd
模塊是對(duì)Excel進(jìn)行讀取操作的滑负,寫入操作需要另外一個(gè)叫xlwt
的模塊來支持。這兒我們只需要讀取操作用含,所以只要引用xlrd
模塊就行了。
這份是我們需要導(dǎo)入讀取的Excel文件帮匾,我們要讀取里面第二列的全部案例編號(hào)啄骇,并取出來。
import xlrd #導(dǎo)入excel 模塊
# 打開EXCEL文檔獲取內(nèi)容
def read_excel():
#文件位置
ExcelFile=xlrd.open_workbook(r'C:\Users\Saber\Desktop\案例編號(hào)清單.xlsx')
#獲取目標(biāo)EXCEL文件sheet名
sheet = ExcelFile.sheet_by_name('Sheet1')
print('該Excel文檔共有' + str(sheet.nrows-1) + '篇文章需要爬取\n')
#獲取第二列的值
rows = sheet.col_values(1)
#刪除第一行的標(biāo)題
rows.pop(0)
# 清洗數(shù)據(jù)瘟斜,把空格的都排除掉
new_excel = []
for a in rows:
a = a.replace(u'\xa0', u'').replace(u' ', u'')
new_excel.append(a)
print('獲取案例編號(hào)成功\n')
return new_excel
因?yàn)镋xcel里會(huì)有空格缸夹,所以獲得原始數(shù)據(jù)后要再把空格都排除掉。\xa0
是不間斷空白符螺句。執(zhí)行一下虽惭,成功獲取到我們希望得到的數(shù)據(jù)。
裝備二:對(duì)文件進(jìn)行讀取和寫入操作
完成了Excel文件的讀取蛇尚,我們還要將數(shù)據(jù)進(jìn)行輸出芽唇。這個(gè)需要引用一個(gè)OS模塊,這個(gè)OS模塊包含在Python的標(biāo)準(zhǔn)庫中取劫,不需要額外的安裝匆笤。這兒我們還是拿剛才的導(dǎo)入Excel表數(shù)據(jù)做例子,將Excel表中的信息輸出到文件中并保存起來谱邪。
def read_excel():
## ......上面代碼省略......##
print('獲取案例編號(hào)成功\n')
# 以寫的方式打開ExcelData.txt
pageFile = open('ExcelData.txt','a+')
# 寫入內(nèi)容
pageFile.write('該EXCEL文檔共有' + str(sheet.nrows-1) + '篇文章需要爬取\n')
# 打開了記得還要關(guān)閉
pageFile.close()
return new_excel
在read_excel()
末尾加入這么三行代碼炮捧。即可以完成文件的打開,內(nèi)容寫入惦银,文件關(guān)閉的操作咆课,非常簡單。效果如下圖所示扯俱。
這里要講解一下open()
這個(gè)方法书蚪。這個(gè)方法里面需要傳入2個(gè)參數(shù)open("文件名","打開方式")
蘸吓,其中打開方式中有很多種善炫。我在這兒選擇了a+的方式,因?yàn)樗麜?huì)判斷文件是否存在库继,不存在則新建箩艺,存在則追加數(shù)據(jù)窜醉,非常適合這次的使用場景。
r 打開只讀文件艺谆,該文件必須存在榨惰。
r+ 具有讀寫屬性,從文件頭開始寫静汤,保留原文件中沒有被覆蓋的內(nèi)容琅催,文件必須存在。
w 打開只寫文件虫给,若文件存在則文件長度清為0藤抡,即該文件內(nèi)容會(huì)消失。若文件不存在則建立該文件抹估。
w+ 具有讀寫屬性缠黍,寫的時(shí)候如果文件存在,會(huì)被清空药蜻,從頭開始寫瓷式,如文件不存在則創(chuàng)建該文件。
a 以附加的方式打開只寫文件语泽。若文件不存在贸典,則會(huì)建立該文件,如果文件存在踱卵,寫入的數(shù)據(jù)會(huì)被加到文件尾廊驼,即文件原先的內(nèi)容會(huì)被保留。
a+ 以附加方式打開可讀寫的文件惋砂。若文件不存在蔬充,則會(huì)建立該文件,如果文件存在班利,寫入的數(shù)據(jù)會(huì)被加到文件尾后饥漫,即文件原先的內(nèi)容會(huì)被保留。
w+與r+區(qū)別:r+:可讀可寫罗标,若文件不存在庸队,報(bào)錯(cuò);w+: 可讀可寫闯割,若文件不存在彻消,創(chuàng)建
r+與a+區(qū)別:r+,可讀寫宙拉,文件必須文件宾尚,從文件開頭開始寫;a+,可讀寫煌贴,文件存在則在文件末尾追加寫御板;文件不存在則創(chuàng)建文件
更詳細(xì)的講解可以參考這篇文章:python文件操作
到此為止,小爬蟲的兩個(gè)新裝備都介紹完畢啦牛郑,我們要對(duì)爬蟲改造下怠肋,讓他能一鍵自動(dòng)按照指定Excel表中的案例編號(hào)進(jìn)行自動(dòng)爬取,并輸出保存爬取到的內(nèi)存淹朋。
改造小爬蟲
在上面我們獲取了全部需要爬取的案例編號(hào)后笙各,進(jìn)入網(wǎng)站發(fā)現(xiàn),每篇文章的caseId編號(hào)并不是使用這個(gè)案例編號(hào)的础芍,需要通過案例編號(hào)搜索杈抢,來獲取每篇文章的caseId,然后才能根據(jù)這個(gè)caseId來對(duì)文章和文章的評(píng)論進(jìn)行訪問仑性。那么春感,我們要先通過這個(gè)案例編號(hào)來獲取文章的caseId。
輸入案例編號(hào)虏缸,點(diǎn)擊搜索后會(huì)出現(xiàn)相對(duì)應(yīng)的文章。
然后對(duì)文章標(biāo)題進(jìn)行審查元素嫩实,可以看到這是個(gè)超鏈接刽辙,文章caseId就在這個(gè)超鏈接中http://xxx.action?caseId=287270
。但是經(jīng)過摸索甲献,發(fā)現(xiàn)前面的那個(gè)input標(biāo)簽的value也帶有這個(gè)caseId宰缤,而且這個(gè)input標(biāo)簽全文只有2個(gè),比起a標(biāo)簽來更方便解析晃洒,于是我決定取這個(gè)input標(biāo)簽中value值慨灭。
通過抓取請(qǐng)求,分析球及,這是一個(gè)POST請(qǐng)求氧骤。Form參數(shù)一共有6個(gè),需要填寫的有3個(gè)吃引,其中核心參數(shù)就是這個(gè)caseSn筹陵。
# 爬取文章鏈接
class BeautifulGetUrl():
def __init__(self,sn,header): #類的初始化操作
self.article_caseId = [] #爬取到的caseId都放到這個(gè)list中,實(shí)例化這個(gè)類后可以隨時(shí)調(diào)用
self.headers = header #給請(qǐng)求指定一個(gè)請(qǐng)求頭來模擬chrome瀏覽器
self.web_url = 'http://net.chinamobile.com/cmccnkms-case/web/casemajor/caseList.action' #要訪問的網(wǎng)頁地址
self.caseSn = sn
def get_caseId(self):
print('開始文章CaseID獲取的POST請(qǐng)求')
for x in self.caseSn:
web_data = {
'pageNum':'',
'majorName':'無線',
'orderType':'ZRequestTime',
'caseTitle':'',
'caseSn':x,
'caseAuthor':''
}
r = requests.post(self.web_url,data=web_data, headers=self.headers)
find_tag = BeautifulSoup(r.text, 'lxml').find_all('input',type='checkbox')
#判斷是否可以搜索到文章,搜不到就把內(nèi)容置為-1
if len(find_tag) == 1:
self.article_caseId.append('-1')
print(x)
print('找不到該篇文章')
else:
self.article_caseId.append(find_tag[1]['value']) #獲取標(biāo)簽的value值
print(x)
print(find_tag[1]['value'])
來解讀一下這段代碼镊尺,這兒因?yàn)檫@幾個(gè)請(qǐng)求的header部分都是一樣的朦佩,所以精簡代碼,把header作為參數(shù)來傳入庐氮,同時(shí)也傳入之前獲取到的案例編號(hào)列表语稠。
通過for循環(huán),將caseSn一個(gè)一個(gè)的傳入弄砍,作為form的參數(shù)仙畦,然后對(duì)地址進(jìn)行post請(qǐng)求输涕。在BeautifulSoup中對(duì)標(biāo)簽為input,類型為checkbox進(jìn)行解析议泵,如果能搜索到這篇文章占贫,就會(huì)有兩個(gè)tag,取第二tag的value值就是我們所需要的caseId先口,然后將這個(gè)追加到之前定義的article_caseId
中型奥。
這兒增加一個(gè)判斷是因?yàn)椋绻撈恼抡趯徍嘶蛘邔徍藳]有通過的話碉京,是搜索不到的厢汹。搜索不到的話,解析到checkbox的tag只有一個(gè)谐宙,我們默認(rèn)取第二個(gè)tag程序就會(huì)報(bào)錯(cuò)烫葬,這個(gè)是需要避免的,所以增加了一個(gè)判斷凡蜻。如果解析出來的tag只有一個(gè)搭综,那么就說明找不到該篇文章,加入一個(gè)-1的標(biāo)識(shí)符划栓,如果不加的話兑巾,那么article_caseId
的下標(biāo)就和之前Excel獲取到的案例編號(hào)下標(biāo)對(duì)不上號(hào)了,必須要加上去忠荞,不能略過蒋歌。
再來改造下最后類的實(shí)例化操作
附上完整的代碼塊
import xlrd #導(dǎo)入excel 模塊
import os #導(dǎo)入os模塊
import requests #導(dǎo)入requests 模塊
from bs4 import BeautifulSoup #導(dǎo)入BeautifulSoup 模塊
# 打開EXCEL文檔獲取內(nèi)容
def read_excel():
......
# 爬取文章caseId
class BeautifulGetCaseId():
def __init__(self,sn,header): #類的初始化操作
......
def get_caseId(self):
......
# 爬取文章案例編號(hào)和當(dāng)前周期有效閱讀數(shù)
class BeautifulGetCaseSNandReadNum():
def __init__(self,i,a,header): #類的初始化操作
......
def get_data(self):
......
# 爬取具體信息
class BeautifulGetData():
def __init__(self,i,caseId,caseSN,header): #類的初始化操作
......
def get_data(self):
......
#給請(qǐng)求指定一個(gè)請(qǐng)求頭來模擬chrome瀏覽器
header = {
......
}
new_excel = read_excel() #從excel中獲取需要的信息
print('獲取案例編號(hào)成功')
beauty = BeautifulGetCaseId(new_excel,header) #創(chuàng)建類的實(shí)例,根據(jù)Excel爬取文章caseId
beauty.get_caseId #執(zhí)行類中的方法
print('爬取文章鏈接成功')
for i,caseId in enumerate(beauty.article_caseId):
if caseId == '-1':
pageFile = open('ExcelData.txt','a+') #以寫的方式打開ExcelData.txt
pageFile.write('這是爬取的第' + str(i+1) + '篇文章\n案例編號(hào):' + new_excel[i] + '\n\n該案例編號(hào)搜索不到相對(duì)應(yīng)的文章\n')
pageFile.close()#開了記得關(guān)
continue
getCaseSN = BeautifulGetCaseSNandReadNum(i,caseId,header) #創(chuàng)建類的實(shí)例委煤,根據(jù)caseId爬取文章基礎(chǔ)信息
getData = BeautifulGetData(i,caseId,new_excel[i],header) #創(chuàng)建類的實(shí)例堂油,根據(jù)caseId爬取文章評(píng)論信息
getCaseSN.get_data()
getData.get_data()
print('爬取具體信息成功')
非常完美,爬取成功碧绞,忍不住都想夸一下能干的自己府框。
后記
截止到現(xiàn)在,一個(gè)能解放人力的小爬蟲誕生了讥邻。但是現(xiàn)在還有個(gè)問題寓免,這個(gè)爬蟲并不是自己使用,而是要交給需要的人來操作使用的计维,交付的人可不會(huì)這些代碼(但是他們?nèi)绻戳宋疫@個(gè)手把手系列袜香,我相信他們也一定能熟練的調(diào)教這只小爬蟲),虛要改一些參數(shù)的話鲫惶,就會(huì)變得很麻煩蜈首。那么我們就需要給這只小爬蟲做一套衣服,讓他成為一只界面友好型的小爬蟲,然后安安心心的交給他人來使用欢策。在下篇文章中我就來講一講Python的圖形界面吆寨。