爬蟲入門教程⑨— 用html和csv文件保存爬取到的數(shù)據(jù)

經(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蛙紫,abrb+這些方法躯护,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)頁示例

上面這個截圖的網(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)到影片的詳情頁。

寫入結(jié)果展示


?

數(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格式)并打開

運行結(jié)果用excel打開

其實文件內(nèi)容很簡單:用,隔開不同的列荤西,一行就是一個新的行:

csv文件內(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!")

用excel打開的結(jié)果

以上就是一部分常見的對數(shù)據(jù)的保存方式了。如果能夠?qū)δ銓W(xué)習(xí)Python與爬蟲的過程起到一點微小的作用妨退,那將是我的無比榮幸妇萄。感謝觀看。


?
傳送門:

下一章:

所有的章節(jié):

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末咬荷,一起剝皮案震驚了整個濱河市冠句,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌幸乒,老刑警劉巖懦底,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異罕扎,居然都是意外死亡基茵,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門壳影,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人弥臼,你說我怎么就攤上這事宴咧。” “怎么了径缅?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵掺栅,是天一觀的道長烙肺。 經(jīng)常有香客問我,道長氧卧,這世上最難降的妖魔是什么桃笙? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮沙绝,結(jié)果婚禮上搏明,老公的妹妹穿的比我還像新娘。我一直安慰自己闪檬,他們只是感情好星著,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著粗悯,像睡著了一般虚循。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上样傍,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天横缔,我揣著相機與錄音,去河邊找鬼衫哥。 笑死茎刚,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的炕檩。 我是一名探鬼主播斗蒋,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼笛质!你這毒婦竟也來了泉沾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤妇押,失蹤者是張志新(化名)和其女友劉穎跷究,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體敲霍,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡俊马,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了肩杈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柴我。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖扩然,靈堂內(nèi)的尸體忽然破棺而出艘儒,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布界睁,位于F島的核電站觉增,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏翻斟。R本人自食惡果不足惜逾礁,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望访惜。 院中可真熱鬧嘹履,春花似錦、人聲如沸疾牲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阳柔。三九已至焰枢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間舌剂,已是汗流浹背济锄。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留霍转,地道東北人荐绝。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像避消,于是被迫代替她去往敵國和親低滩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 概述 java.io 包幾乎包含了所有操作輸入岩喷、輸出需要的類恕沫。所有這些流類代表了輸入源和輸出目標(biāo)。java.io ...
    Steven1997閱讀 9,190評論 1 25
  • @宜風(fēng) 我有一束光明明晃晃 我有一片心飄飄蕩蕩 我有一縷情惆惆悵悵 我有一個夢紛紛揚揚 光 透過心 穿過情 以夢為...
    鄒穎一閱讀 503評論 5 2
  • 首先要講一下幾個理念性的東西纱意,我自己的理解婶溯,或許大家不贊同。不過贊不贊同另當(dāng)別論偷霉,反正我這兒是得先說的迄委。先說說我自...
    cOoKiE_1閱讀 953評論 1 7
  • 碼頭的大喇叭: “云丸號上的士兵們,你們誤會了类少,我們不是不送你們回日本叙身。云丸號,在海上服役多年硫狞,機器老化信轿,抗風(fēng)能力...
    風(fēng)起龍飛閱讀 184評論 0 3