經(jīng)過努力佑吝,我們終于拿到了數(shù)據(jù)了绣否。那么下一步就是要將我們獲取到的數(shù)據(jù)保存起來了,這樣才能給后續(xù)的操作(在網(wǎng)頁上展示洪鸭、數(shù)據(jù)分析挖掘可視化等等)提供便利样刷。
一般我們保存數(shù)據(jù)可以采用多種可選載體,根據(jù)成本览爵、數(shù)據(jù)用途我們分別采用適合自己的載體保存數(shù)據(jù)置鼻。
- 主要的數(shù)據(jù)保存方法有
- 寫入到文本:txt,csv蜓竹,excel...
- 保存到數(shù)據(jù)庫:本地的sqlite箕母、MySQL、mongodb...
由于保存到數(shù)據(jù)庫的操作需要了解數(shù)據(jù)庫相關(guān)知識以及軟件支持俱济,所以我們本章采用多種文本方式寫入嘶是。
先回顧一下上一節(jié)的代碼:
import requests
from bs4 import BeautifulSoup # 從bs4引入BeautifulSoup
#請求網(wǎng)頁
# 舊版教程
# url = "https://movie.douban.com/cinema/later/chengdu/"
# response = requests.get(url)
# 2019-12-23更新,解決不能獲取到響應(yīng)的問題
url = "https://movie.douban.com/cinema/later/chengdu/" # URL不變
# 新增偽裝成Chrome瀏覽器的header
fake_headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36'
}
response = requests.get(url, headers=fake_headers) # 請求參數(shù)里面把假的請求header加上
# 解析網(wǎng)頁
# 初始化BeautifulSoup方法一:利用網(wǎng)頁字符串自帶的編碼信息解析網(wǎng)頁
soup = BeautifulSoup(response.content.decode('utf-8'), 'lxml')
# 初始化BeautifulSoup方法二:手動指定解析編碼解析網(wǎng)頁
# soup = BeautifulSoup(response.content, 'lxml', from_encoding='utf-8')
# print(soup) # 輸出BeautifulSoup轉(zhuǎn)換后的內(nèi)容
all_movies = soup.find('div', id="showing-soon") # 先找到最大的div
# print(all_movies) # 輸出最大的div的內(nèi)容
for each_movie in all_movies.find_all('div', class_="item"): # 從最大的div里面找到影片的div
# print(each_movie) # 輸出每個影片div的內(nèi)容
all_a_tag = each_movie.find_all('a')
all_li_tag = each_movie.find_all('li')
movie_name = all_a_tag[1].text
moive_href = all_a_tag[1]['href']
movie_date = all_li_tag[0].text
movie_type = all_li_tag[1].text
movie_area = all_li_tag[2].text
movie_lovers = all_li_tag[3].text
print('名字:{}蛛碌,鏈接:{}聂喇,日期:{},類型:{}蔚携,地區(qū):{}希太, 關(guān)注者:{}'.format(
movie_name, moive_href, movie_date, movie_type, movie_area, movie_lovers))
-
Python打開文件操作詳解
使用file_obj = open("file_name", 'mode', encoding="encoding")
的方法進(jìn)行操作。
file_name
是你需要讀取或者寫入的文件路徑及文件名(如"../data/ok.txt"
是相對路徑打開酝蜒,如果只寫一個"ok.txt"
誊辉,那么就會默認(rèn)保存到當(dāng)前.py文件或者.ipynb文件的相同文件夾里面)mode
是你指定操作文件的方法,常用的有r
亡脑,w
堕澄,a
,r+
,rb
霉咨,wb
蛙紫,ab
,rb+
這些方法躯护,r
是讀取(read惊来,如果不存在則報錯),w
是寫入(write棺滞,文件不存在則創(chuàng)建裁蚁,如果文件存在則覆蓋)矢渊,a
是追加寫入(文件不存在則創(chuàng)建,文件存在從文件最后開始寫入)枉证,r+
是讀取和寫入矮男。后面加了個b
的,是以二進(jìn)制方式進(jìn)行上述操作(通常用于對圖片室谚、視頻等二進(jìn)制文件進(jìn)行操作)毡鉴,mode默認(rèn)是r。encoding
在前面的章節(jié)說過了秒赤,是我們對文件進(jìn)行操作所遵循的編碼猪瞬,默認(rèn)為當(dāng)前運行環(huán)境編碼。Windows的默認(rèn)編碼是gbk
入篮,linux系統(tǒng)基本上是utf-8
陈瘦。不同的文件可以有不同的編碼,設(shè)置讀取的編碼錯誤要么會報錯潮售,要么就得不到正確的內(nèi)容痊项。file_obj
是一個文件對象(Python里面也是萬物皆對象,所以不要愁沒有對象了)酥诽,之后我們讀取鞍泉、寫入數(shù)據(jù)都通過這個對象進(jìn)行操作。
Python讀取文件方法
file_obj.read()
肮帐,一次性讀取文件所有的內(nèi)容作為一個字符串咖驮。
file_obj.readlines()
,一次性讀取文件所有內(nèi)容训枢,但每一行作為一個字符串并放在一個list(數(shù)組)里面游沿。
file_obj.readline(limit)
,從上次讀取的行數(shù)開始肮砾,讀取limit
行,limit默認(rèn)為1袋坑。該方法通常用在由于文件過大不能一次性讀取完畢一個文件的時候)仗处。Python寫入文件的方法
file_obj.write(anystr)
,該方法接受一個字符串枣宫,并將字符串寫入婆誓。
file_obj.writelines(list_of_str)
,該方法接受一個內(nèi)部全是字符串的list數(shù)組也颤,并將所有字符串一行一個寫入(自動添加換行符)洋幻。關(guān)閉文件
file_obj.close()
關(guān)閉文件對象。打開了一個文件之后要記得關(guān)閉翅娶,否則可能會出現(xiàn)不可控的問題文留。但是如果用with方法打開了文件好唯,則不需要手動關(guān)閉文件,在with語句塊運行結(jié)束后燥翅,會自動關(guān)閉文件骑篙。
示例
# 需要手動關(guān)閉文件
file_obj = open("ok.txt", 'r', encoding="utf-8")
content = file_obj.read()
file_obj.close()
# 不需要手動關(guān)閉文件
with open("ok.txt", 'r', encoding="utf-8") as file_obj:
content = file_obj.read()
?
把數(shù)據(jù)保存到 html 文件
由于txt文件難度較低且所學(xué)內(nèi)容被本小節(jié)囊括了,所以我們直接從保存數(shù)據(jù)到HTML文件開始森书。
我們的目標(biāo)是:
上面這個截圖的網(wǎng)頁的代碼是這樣的(為了簡潔美觀靶端,所以采用了bootstrap的css樣式):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>豆瓣電影即將上映影片信息</title>
<link rel="stylesheet">
</head>
<body>
<h2 class="text-center">豆瓣電影即將上映影片信息</h2>
<table class="table table-striped table-hover mx-auto text-center">
<thead>
<tr>
<th>影片名</th>
<th>上映日期</th>
<th>影片類型</th>
<th>地區(qū)</th>
<th>關(guān)注者數(shù)量</th>
</tr>
</thead>
<tbody>
<tr>
<td><a >測試名1</a></td>
<td>測試日期1</td>
<td>測試類型1</td>
<td>測試地區(qū)1</td>
<td>測試關(guān)注者1</td>
</tr>
<tr>
<td><a >測試名2</a></td>
<td>測試日期2</td>
<td>測試類型2</td>
<td>測試地區(qū)2</td>
<td>測試關(guān)注者2</td>
</tr>
</tbody>
</table>
</body>
</html>
從這個代碼,我們可以知道凛膏,只要我們重復(fù)生成<tbody>標(biāo)簽里面的<tr>...<tr>
中間的內(nèi)容杨名,并把我們的數(shù)據(jù)填進(jìn)去,數(shù)據(jù)就會一行一行地被填充到表格中了猖毫。<tbody>
前后的代碼我們就只需要復(fù)制過來寫入就好了台谍。
所以我們就拿著之前的代碼開始操作了:
注:python 里面三個"
圍起來的字符會被看做是一整個字符串,避免了換行符的麻煩鄙麦。
.format()
這個方法的用法是把字符串里面的{}
字符典唇,按次序一一替換成 format() 接受的所有參數(shù)。
import requests
from bs4 import BeautifulSoup # 從bs4引入BeautifulSoup
#請求網(wǎng)頁
# 舊版教程
# url = "https://movie.douban.com/cinema/later/chengdu/"
# response = requests.get(url)
# 2019-12-23更新胯府,解決不能獲取到響應(yīng)的問題
url = "https://movie.douban.com/cinema/later/chengdu/" # URL不變
# 新增偽裝成Chrome瀏覽器的header
fake_headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36'
}
response = requests.get(url, headers=fake_headers) # 請求參數(shù)里面把假的請求header加上
# 初始化BeautifulSoup方法一:利用網(wǎng)頁字符串自帶的編碼信息解析網(wǎng)頁
soup = BeautifulSoup(response.content.decode('utf-8'), 'lxml')
# 初始化BeautifulSoup方法二:手動指定解析編碼解析網(wǎng)頁
# soup = BeautifulSoup(response.content, 'lxml', from_encoding='utf-8')
# print(soup) # 輸出BeautifulSoup轉(zhuǎn)換后的內(nèi)容
all_movies = soup.find('div', id="showing-soon") # 先找到最大的div
# print(all_movies) # 輸出最大的div的內(nèi)容
html_file = open('data.html', 'w', encoding="utf-8")
html_file.write("""
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>豆瓣電影即將上映影片信息</title>
<link rel="stylesheet">
</head>
<body>
<h2 class="text-center">豆瓣電影即將上映影片信息</h2>
<table class="table table-striped table-hover mx-auto text-center">
<thead>
<tr>
<th>影片名</th>
<th>上映日期</th>
<th>影片類型</th>
<th>地區(qū)</th>
<th>關(guān)注者數(shù)量</th>
</tr>
</thead>
<tbody>
""")
for each_movie in all_movies.find_all('div', class_="item"): # 從最大的div里面找到影片的div
# print(each_movie) # 輸出每個影片div的內(nèi)容
all_a_tag = each_movie.find_all('a')
all_li_tag = each_movie.find_all('li')
movie_name = all_a_tag[1].text
moive_href = all_a_tag[1]['href']
movie_date = all_li_tag[0].text
movie_type = all_li_tag[1].text
movie_area = all_li_tag[2].text
# 替換字符串里面的 想看 兩個字為空介衔,使得更加美觀
movie_lovers = all_li_tag[3].text.replace("想看", '')
print('名字:{},鏈接:{}骂因,日期:{}炎咖,類型:{},地區(qū):{}寒波, 關(guān)注者:{}'.format(
movie_name, moive_href, movie_date, movie_type, movie_area, movie_lovers))
html_file.write("""
<tr>
<td><a href="{}">{}</a></td>
<td>{}</td>
<td>{}</td>
<td>{}</td>
<td>{}</td>
</tr>
""".format(moive_href, movie_name, movie_date, movie_type, movie_area, movie_lovers))
html_file.write("""
</tbody>
</table>
</body>
</html>
""")
html_file.close()
print("write_finished!")
運行一下乘盼,成功輸出。然后我們回到 jupyter 的首頁俄烁,找到我們的data.html
绸栅,點擊文件名打開網(wǎng)頁,就可以看到如下的結(jié)果了页屠,并且我們點擊這些影片的名字粹胯,都會自動跳轉(zhuǎn)到影片的詳情頁。
?
數(shù)據(jù)保存到csv文件
首先介紹一下csv文件辰企,這是個類 txt 的表格文件风纠,讀取和寫入都相對excel的表格文件更加簡單方便,所以在數(shù)據(jù)領(lǐng)域使用較多牢贸。
要使用csv模塊竹观,我們首先需要import csv
,然后把一個文件對象作為參數(shù)傳給csv.writer()
或者csv.reader()
,然后我們就對這個writer/reader進(jìn)行讀寫操作了臭增。
寫入是調(diào)用writer的writerow()
方法懂酱。writerow方法接受一個由字符串組成的 list 數(shù)組,然后就會把這個list的內(nèi)容按照規(guī)定寫入到csv文件速址。
讀取則是對reader進(jìn)行遍歷玩焰,每一輪遍歷的結(jié)果返回一行的數(shù)據(jù)組成的 list數(shù)組。
寫入示例:
import csv
# Windows默認(rèn)編碼是gbk芍锚,如果用utf-8昔园,excel打開可能會亂碼
# newline='' 是為了讓writer自動添加的換行符和文件的不重復(fù),防止出現(xiàn)跳行的情況
file_obj = open('csvtest.csv', 'w', encoding="gbk", newline='')
writer = csv.writer(file_obj)
a_row = ['你好', 'hello', 'thank', 'you']
row_2 = ['how', 'are', 'you', 'indian', 'mifans']
writer.writerow(a_row)
writer.writerow(row_2)
file_obj.close()
print('finished!')
我們在Windows文件管理器打開當(dāng)前代碼文件夾并炮,(如果沒有指定jupyter啟動路徑并且是以win+x鍵啟動的jupyter默刚,那么jupyter的代碼和生成的文件默認(rèn)是在你的 C:/USER(用戶)/username
文件夾里面,username是你的電腦的用戶名逃魄。)
找到這個csvtest.csv文件(默認(rèn)就是excel或者wps格式)并打開
其實文件內(nèi)容很簡單:用,
隔開不同的列荤西,一行就是一個新的行:
讀取示例:
import csv
# 讀取的編碼要和寫入的保持一致
file_obj = open('csvtest.csv', 'r', encoding="gbk")
reader = csv.reader(file_obj)
for row in reader:
print(row)
file_obj.close()
print('finished!')
運行結(jié)果輸出:
['你好', 'hello', 'thank', 'you']
['how', 'are', 'you', 'indian', 'mifans']
finished!
OK,下一步我們就試著把影片信息存到csv文件中
import csv
import requests
from bs4 import BeautifulSoup # 從bs4引入BeautifulSoup
# 請求網(wǎng)頁
url = "https://movie.douban.com/cinema/later/chengdu/"
response = requests.get(url)
# 初始化BeautifulSoup方法一:利用網(wǎng)頁字符串自帶的編碼信息解析網(wǎng)頁
soup = BeautifulSoup(response.content.decode('utf-8'), 'lxml')
# 初始化BeautifulSoup方法二:手動指定解析編碼解析網(wǎng)頁
# soup = BeautifulSoup(response.content, 'lxml', from_encoding='utf-8')
# print(soup) # 輸出BeautifulSoup轉(zhuǎn)換后的內(nèi)容
all_movies = soup.find('div', id="showing-soon") # 先找到最大的div
# print(all_movies) # 輸出最大的div的內(nèi)容
csv_file = open('data.csv', 'w', encoding="gbk", newline='')
writer = csv.writer(csv_file)
writer.writerow(["影片名", "鏈接", "上映日期", "影片類型", "地區(qū)", "關(guān)注者"]) # 寫入標(biāo)題
for each_movie in all_movies.find_all('div', class_="item"): # 從最大的div里面找到影片的div
# print(each_movie) # 輸出每個影片div的內(nèi)容
all_a_tag = each_movie.find_all('a')
all_li_tag = each_movie.find_all('li')
movie_name = all_a_tag[1].text
moive_href = all_a_tag[1]['href']
movie_date = all_li_tag[0].text
movie_type = all_li_tag[1].text
movie_area = all_li_tag[2].text
movie_lovers = all_li_tag[3].text.replace("想看", '')
print('名字:{}伍俘,鏈接:{}邪锌,日期:{},類型:{}癌瘾,地區(qū):{}觅丰, 關(guān)注者:{}'.format(
movie_name, moive_href, movie_date, movie_type, movie_area, movie_lovers))
writer.writerow([movie_name, moive_href, movie_date, movie_type, movie_area, movie_lovers])
csv_file.close()
print("write_finished!")
以上就是一部分常見的對數(shù)據(jù)的保存方式了。如果能夠?qū)δ銓W(xué)習(xí)Python與爬蟲的過程起到一點微小的作用妨退,那將是我的無比榮幸妇萄。感謝觀看。
?
傳送門:
下一章:
所有的章節(jié):