用理工科思維看待這個世界
崇尚的學習思維是:輸入,輸出平衡,且平衡點不斷攀升。
曾經有大神告誡說:沒事別瞎寫文章;所以,很認真的寫的是能力范圍內的,看客要是看不懂,不是你的問題,問題在我,得持續輸入,再輸出。
今天的主題是:實戰爬取電影,并存儲至MySQL數據庫
1:框架
序號 | 目標 | 說明 |
---|---|---|
01 | 抓取目標分析 | -目標是什么 |
02 | 分解任務 | -- |
03 | MySQL建表操作 | 本地建表 |
04 | 實戰抓取 | -- |
05 | 參考及總結 | -- |
2:目標
任務是:抓取網站數據,存放至MySQL數據庫中。
效果顯示:抓取的目標存放至本地MySQL數據庫
初始URL
url = https://movie.douban.com/top250
字段:
Film : 電影名稱
Director: 電影導演
Rates : 評分數
Numbers : 評分人數
Url: 電影鏈接
Describe: 電影介紹 (網站的一句話,經典臺詞之類的)
3:任務分解
具體點擊網頁審查元素:鏈接
- 字段的正則表達式
電影名稱:
Film_pattern = r'<span class="title">(.*?)</span>'
電影導演:
Director_pattern = r'<p class="">(.*?)</p>'
評分數:
Rates_pattern = r'<span class="rating_num" property="v:average">(.*?)</span>'
評分人數:先抓大,再在大的里面匹配所需的文本信息
Number_pattern_large = r'<div class="star">(.*?)</div>'
Number_pattern_small = r'<span>(.*?)</span>'
電影鏈接:先抓大,再在大的里面匹配所需的文本信息
Urlfilm_pattern_large = r'<div class="hd">(.*?)</div>'
Urlfilm_pattern_small = r'<a href="(.*?)"'
電影介紹:
Describe_pattern = r'<span class="inq">(.*?)</span>'
- URL的分析:
由翻頁,自己匹配出網址:(也可以網址抓取)。10頁。
urls = ["https://movie.douban.com/top250?start={}&filter=".format(i) for i in range(0,250,25)]
網址分析完成,正則分析完成。任務完成了大半。
4:數據庫建表操作
在本地:數據庫名為:exercise 下創建一個表名為:douban_film
建表的SQL語法:參照w3school
CREATE TABLE `douban_film` (
`Film` CHAR(32) DEFAULT NULL COMMENT '電影名稱',
`Director` CHAR(32) DEFAULT NULL COMMENT '電影導演',
`Rates` FLOAT DEFAULT NULL COMMENT '評分數',
`Number` CHAR(16) DEFAULT NULL COMMENT '評分人數',
`Url` CHAR(128) DEFAULT NULL COMMENT '評分人數',
`Describe` CHAR(128) DEFAULT NULL COMMENT '電影介紹'
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='豆瓣電影250介紹'
`douban_film`
# 執行sql語句就可以創建一個表,各字段及其屬性如上示
5:實戰抓取
單獨使用正則,會出現很多難以匹配(可能沒有嘗試其他匹配規則)。需要對網頁進行不斷的分析。
抓取核心代碼:(大神輕拍代碼...)
# 網頁抓取字段示例
def content_json(self, content):
Film_all = re.findall(self.Film_pattern, content, re.S)
Film = []
for one_film in Film_all:
if " " not in one_film:
Film.append(one_film)
Director_all = re.findall(self.Director_pattern, content, re.S)
Director = []
for one_Director in Director_all:
one = self.str_replace(one_Director)
Director.append(one)
Rates = re.findall(self.Rates_pattern, content, re.S)
Number_large = re.findall(self.Number_pattern_large, content, re.S)
Number = []
for one_number in Number_large:
Number_one = re.findall(self.Number_pattern_small, one_number, re.S)[0]
Number.append(Number_one)
Describe = re.findall(self.Describe_pattern, content, re.S)
Url_largre = re.findall(self.Urlfilm_pattern_large, content, re.S)
Url =[]
for one_url in Url_largre:
Url_one = re.findall(self.Urlfilm_pattern_small, one_url, re.S)[0]
Url.append(Url_one)
Film_collection = []
for Film, Director, Rates, Number, Describe, Url in zip(Film, Director, Rates, Number, Describe, Url):
data = {
"Film": Film,
"Director": Director,
"Rates": Rates,
"Number": Number,
"Describe": Describe,
"Url": Url
}
Film_collection.append(data)
return Film_collection
# 文本匹配會有很多不需要的字段,如下函數實現數據清洗
def str_replace(self, str_one):
str_one_1 = str_one.replace("\n", '')
str_one_2 = str_one_1.replace("<br>", '')
str_one_3 = str_one_2.replace(" ", '')
str_one_4 = str_one_3.replace("\t", "")
str_one_5 = str_one_4.replace(" ", '').strip()
return str_one_5
# 單獨寫sql語句比較繁瑣,如下函數實現JSON格式數據轉換成SQL語句
import copy
def json_to_mysql(json_obj, table, sql_type="insert"):
local_copy = copy.deepcopy(json_obj)
if sql_type == "insert":
sql_part1 = "insert into " + table
keys = local_copy.keys()
sql_part2 = "("
for key in keys:
sql_part2 += "`%s`"%(key)
sql_part2 += ","
sql_part2 = sql_part2.rstrip(",")
sql_part2 += ")"
sql_part3 = "("
for key in keys:
sql_part3 += "'" + (local_copy[key]) + "'"
sql_part3 += ","
sql_part3 = sql_part3.rstrip(",")
sql_part3 += ")"
sql = sql_part1 + " " + sql_part2 + " values " + sql_part3
return sql
核心代碼已經完成:
整體思路如下:
- 分析首頁文本信息的正則表達式
- 抓取首頁的字段
- 對字段進行數據的清洗,去掉不需要的信息
- 將數據結構化
- 循環操作
- 獲取的全部信息執行sql語句,存入已經建表的MySQL數據庫中
完整版代碼:完整版代碼
另一款數據庫可視化工具顯示效果:
可知:抓取了243條信息。全站存在250條數據。代碼存在Bug...
你懂的??梢岳^續重構。
6:參考及總結
自勉:
在通往牛逼的路上,別人一定存在許多值得借鑒的地方。
學習學習在學習
實踐實踐再實踐
感謝互聯網時代,讓學習如此觸手可及
關于本人:
國內小碩,半路出家的IT學習者。
興趣領域:爬蟲 , 數據科學
本人正在構建一個共同成長爬蟲小型社群。QQ群:539065787
持續精進。如果理念相似,歡迎加入。
文檔及代碼托管在Github上。