老版:Python 爬取內容存入Excel實例
這是之前用python2.7
寫的,最近看博友評論,因網頁結構調整和python3
的普及,代碼運行後報錯、得不到數據。於是,使用python3重寫了一次,順便做下改進。
網頁解析可以去看下之前的文章,這裏不作贅述。
環境:python 3.6.5
所需包安裝:pip install requests bs4 lxml openpyxl
1、抓取代碼
先上代碼,後分析
'''
function:爬取豆瓣top250的電影信息,並寫入Excel文件
env:python3.6.5
author:jxc
'''
import requests
import re
from openpyxl import workbook # 寫入Excel表所用
from bs4 import BeautifulSoup as bs
class Top250:
def __init__(self):
#起始地址
self.start_url = 'https://movie.douban.com/top250'
#請求頭,瀏覽器模擬
self.headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',
}
#爬取頁數
self.page_num = 10
'''url拼接'''
def get_page_url(self):
n = 0 #第一頁開始,下標0
while n<self.page_num:
yield self.start_url+'?start={}&filter='.format(n*25)
n += 1
'''獲取頁面源碼'''
def getHtml(self):
gu = self.get_page_url() #url生成器
for url in gu:
html = requests.get(url,headers=self.headers).content.decode('utf-8')
yield html
''''電影數據提取'''
def getData(self):
gh = self.getHtml() # html源碼生成器
for html in gh: # html:網頁源碼
soup = bs(html, 'lxml')
for info in soup.find_all('div', class_='info'):
c_name = info.find('span',class_='title').text.strip() # 得到電影中文名
message = info.select('div.bd p')[0].text.strip() #得到導演、主演、年份、地區信息
yat = re.search('[0-9]+.*\/?', message).group().split('/',1) #得到年份、地區、類型信息列表
year,area,type = yat[0],yat[1].rsplit('/',1)[0],yat[1].rsplit('/',1)[1]#得到年份、地區、類型
da = re.search('導演.+\s',message).group().strip()+'...' #得到導演、主演混合信息
director = re.findall('導演:(.+?)\s',da)[0].strip() #得到導演信息
#得到主演信息,不存在時發生異常,進行異常處理
try:
mainActors = re.findall('主演:(.+?)[.,]+',da)[0].strip()
except IndexError:
mainActors = '暫無主演信息'
mark_info = info.find('div',class_='star') #得到評分、評價人數混合信息
score= mark_info.find('span',class_='rating_num').text.strip()#得到評分
count = re.search('[0-9]+',mark_info.select('span')[3].text).group() #得到評價人數
#得到簡介,捕捉不存在時的異常
try:
quote = info.select('p.quote span')[0].text.strip()
except IndexError:
quote = '該影片暫時無簡介'
yield [c_name,year,area,type,director,mainActors,score,count,quote]
'''保存到excel文件
:param file_name:文件名
'''
def saveToExcel(self,file_name):
wb = workbook.Workbook() # 創建Excel對象
ws = wb.active # 獲取當前正在操作的表對象
ws.append(['電影名', '年份', '地區', '劇情類型', '導演', '主演', '評分', '評論人數', '簡介'])
gd = self.getData() #數據生成器
for data in gd:
ws.append(data)
wb.save(file_name)
if __name__ == '__main__':
top = Top250()
try:
top.saveToExcel('top250.xlsx')
print('抓取成功')
except Exception as e:
print('抓取失敗,原因:%s'%e)
2、代碼要點分析
- 在獲取各屬性(名稱、導演、主演…)數據時,大量使用了
re
進行匹配抓取,不熟悉的可以先去看下正則表達式-菜鳥教程 rsplit
方法,從後往前進行切片。代碼中的rsplit('/',1)
意爲從後往前,以/
爲切片元素,只切 1 次。re.findall()
方法,在前後加上不變的條件,變化的部分使用()
包裹,這樣就能直接得到想要的信息,不用再次切片獲取。如代碼中的re.findall('導演:(.+?)\s',da)[0]
,就能直接得到導演信息。- 部分電影無主演或簡介信息,所以使用
try...except
捕獲異常
3、本次改進的地方
- 封裝爲類,提高了代碼擴展性
- 改進了數據抓取方法,提高了代碼效率
- 使用
生成器
,實現抓取流水線操作 - 改進了信息缺失的判斷邏輯,並進行異常處理
歡迎留言討論~
博主其他系列文章:
[1] 【python實用特性】-切片
[2] 【python實用特性】- 迭代、可迭代對象、迭代器
[5] Python如何爬取動態網頁數據