python爬蟲 貓眼電影和電影天堂資料csv和mysql儲存過程解析
字串常用方法
# 去掉左右空格 'hello world'.strip() # 'hello world' # 按指定字元切割 'hello world'.split(' ') # ['hello','world'] # 替換指定字串 'hello world'.replace(' ','#') # 'hello#world'
csv模組
作用:將爬取的資料存放到本地的csv檔案中
使用流程
- 匯入模組
- 開啟csv檔案
- 初始化寫入物件
- 寫入資料(引數為列表)
import csv with open('test.csv','w') as f: writer = csv.writer(f) # 初始化寫入物件 # 寫一行 writer.writerow(['超哥哥',20]) writer.writerow(['步驚雲',22]) with open('test.csv','a') as f: writer = csv.writer(f) # 寫多行 data_list = [('聶風',23),('秦霜',30)] writer.writerows(data_list)
Windows中使用csv模組預設會在每行後面新增一個空行,使用newline=''可解決
with open('xxx.csv','w',newline='') as f:
貓眼電影top100抓取案例
確定URL網址
貓眼電影 - 榜單 - top100榜 目標
電影名稱、主演、上映時間 操作步驟
1、檢視是否為動態載入
右鍵 - 檢視網頁原始碼 - 搜尋爬取關鍵字(檢視在原始碼中是否存在)
2、找URL規律
- 第1頁:https://maoyan.com/board/4?offset=0
- 第2頁:https://maoyan.com/board/4?offset=10
- 第n頁:offset=(n-1)*10
3、正則表示式
<div class="movie-item-info">.*?title="(.*?)".*?class="star">(.*?)</p>.*?releasetime">(.*?)</p>
4、編寫程式框架,完善程式
- 列印程式執行時間
- 隨機的User-Agent,(確保每次發請求使用隨機)
- 資料爬下來後做處理(字串),定義成字典
- 一條龍: 獲取 -> 呼叫解析 -> 資料處理
- 貓眼電影資料存入本地 maoyanfilm.csv 檔案
from urllib import request import time import re import csv import random class MaoyanSpider(object): def __init__(self): self.page = 1 # 用於記錄頁數 self.url = 'https://maoyan.com/board/4?offset={}' self.agent = [ 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML,like Gecko) Chrome/14.0.835.163 \ Safari/535.1','Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0','Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; \ .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3)','Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML,like Gecko) Chrome/14.0.835.163 Safari/535.1'] # 請求 def get_page(self,url): headers = {'User-Agent': random.choice(self.agent)} # 每次使用隨機的user-agent req = request.Request(url=url,headers=headers) # 建立請求物件 res = request.urlopen(req) # 發起請求 html = res.read().decode('utf-8') # 獲取請求內容 self.parse_page(html) # 直接呼叫解析函式 # 解析 def parse_page(self,html): pattren = re.compile( '<div class="movie-item-info">.*?title="(.*?)".*?class="star">(.*?)</p>.*?releasetime">(.*?)</p>',re.S) r_list = pattren.findall(html) # rlist: [('霸王別姬','\n 主演:張國榮,張豐毅,鞏俐\n ','上映時間:1993-01-01'),(...),(...)] self.write_page(r_list) # 寫入csv檔案 # # 儲存,列印輸出 # def write_page(self,r_list): # one_film_dict = {} # for rt in r_list: # one_film_dict['name'] = rt[0].strip() # one_film_dict['star'] = rt[1].strip() # one_film_dict['time'] = rt[2].strip()[5:15] # # print(one_film_dict) # 儲存到csv檔案(writerows) -- 推薦使用此方法 def write_page(self,r_list): # 空列表,最終writerows()的引數: [(),(),()] film_list = [] with open('maoyan.csv','a',newline="") as f: writer = csv.writer(f) for rt in r_list: # 把處理過的資料定義成元組 t = (rt[0],rt[1].strip(),rt[2].strip()[5:15]) film_list.append(t) writer.writerows(film_list) def main(self): for offset in range(0,31,10): url = self.url.format(offset) self.get_page(url) time.sleep(random.randint(1,3)) print('第%d頁爬取完成' % self.page) self.page += 1 if __name__ == '__main__': start = time.time() spider = MaoyanSpider() spider.main() end = time.time() print('執行時間: %.2f' % (end - start))
資料持久化儲存(MySQL資料庫)
讓我們來回顧一下pymysql模組的基本使用
import pymysql db = pymysql.connect('localhost','root','123456','maoyandb',charset='utf8') cursor = db.cursor() # 建立遊標物件 # execute()方法第二個引數為列表傳參補位 cursor.execute('insert into film values(%s,%s,%s)',['霸王別姬','張國榮','1993']) db.commit() # 提交到資料庫執行 cursor.close() # 關閉 db.close()
讓我們來回顧一下pymysql中executemany()的用法
import pymysql # 資料庫連線物件 db = pymysql.connect('localhost',charset='utf8') cursor = db.cursor() # 遊標物件 ins_list = [] # 存放所有資料的大列表 for i in range(2): name = input('請輸入第%d個學生姓名:' % (i + 1)) age = input('請輸入第%d個學生年齡:' % (i + 1)) ins_list.append([name,age]) ins = 'insert into t3 values(%s,%s)' # 定義插入語句 cursor.executemany(ins,ins_list) # 一次資料庫的IO操作可插入多條語句,提升效能 db.commit() # 提交到資料庫執行 cursor.close() # 關閉遊標 db.close() # 關閉資料庫 ins = 'insert into maoyanfilm values(%s,%s)' cursor.execute(['霸王','國榮','1991']) cursor.executemany([ ['月光寶盒','周星馳','1993'],['大聖娶親','1993']])
練習:把貓眼電影案例中電影資訊存入MySQL資料庫中(儘量使用executemany方法)
from urllib import request import time import re import pymysql import random class MaoyanSpider(object): def __init__(self): self.page = 1 # 用於記錄頁數 self.url = 'https://maoyan.com/board/4?offset={}' self.ua_list = [ 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML,like Gecko) \ Chrome/14.0.835.163 Safari/535.1','Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; \ .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3)'] # 建立資料庫連線物件和遊標物件 self.db = pymysql.connect('localhost',charset='utf8') self.cursor = self.db.cursor() # 獲取 def get_page(self,url): # 每次使用隨機的user-agent headers = {'User-Agent': random.choice(self.ua_list)} req = request.Request(url=url,headers=headers) res = request.urlopen(req) html = res.read().decode('utf-8') self.parse_page(html) # 直接呼叫解析函式 # 解析 def parse_page(self,re.S) # rlist: [('霸王別姬','1993'),()] r_list = pattren.findall(html) print(r_list) self.write_page(r_list) # 存入mysql資料庫(executemany([ [],[],[] ])) def write_page(self,r_list): film_list = [] ins = 'insert into filmtab values(%s,%s)' # 定義插入語句 # 處理資料,放到大列表film_list中 for rt in r_list: one_film = [rt[0],rt[2].strip()[5:15]] # 新增到大列表中 film_list.append(one_film) # 一次資料庫IO把1頁資料存入 self.cursor.executemany(ins,film_list) # 提交到資料庫執行 self.db.commit() def main(self): for offset in range(0,3)) print('第%d頁爬取完成' % self.page) self.page += 1 # 斷開資料庫(所有頁爬完之後) self.cursor.close() self.db.close() if __name__ == '__main__': start = time.time() spider = MaoyanSpider() spider.main() end = time.time() print('執行時間: %.2f' % (end - start))
讓我們來做個SQL命令查詢
1、查詢20年以前的電影的名字和上映時間
select name,time from filmtab where time<(now()-interval 20 year);
2、查詢1990-2000年的電影名字和上映時間
select name,time from filmtab where time>='1990-01-01' and time<='2000-12-31';
讓我們來複習一下mongdb資料庫
import pymongo # 1.連線物件 conn = pymongo.MongoClient(host='127.0.0.1',port=27017) db = conn['maoyandb'] # 2.庫物件 myset = db['filmtab'] # 3.集合物件 myset.insert_one({'name': '趙敏'}) # 4.插入資料庫
練習:把貓眼電影案例中電影資訊存入MongDB資料庫中
from urllib import request import re import time import random import pymongo class MaoyanSpider(object): def __init__(self): self.url = 'https://maoyan.com/board/4?offset={}' # 計數 self.num = 0 # 建立3個物件 self.conn = pymongo.MongoClient('localhost',27017) self.db = self.conn['maoyandb'] self.myset = self.db['filmset'] self.ua_list = [ 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML,like Gecko) Chrome/14.0.835.163 Safari/535.1','Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET \ CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3)',] def get_html(self,url): headers = { 'User-Agent': random.choice(self.ua_list) } req = request.Request(url=url,headers=headers) res = request.urlopen(req) html = res.read().decode('utf-8') # 直接呼叫解析函式 self.parse_html(html) def parse_html(self,html): re_bds = r'<div class="movie-item-info">.*?title="(.*?)".*?class="star">(.*?)</p>.*?releasetime">(.*?)</p>' pattern = re.compile(re_bds,re.S) # film_list: [('霸王別姬',()] film_list = pattern.findall(html) # 直接呼叫寫入函式 self.write_html(film_list) # mongodb資料庫 def write_html(self,film_list): for film in film_list: film_dict = { 'name': film[0].strip(),'star': film[1].strip(),'time': film[2].strip()[5:15] } # 插入mongodb資料庫 self.myset.insert_one(film_dict) def main(self): for offset in range(0,10): url = self.url.format(offset) self.get_html(url) time.sleep(random.randint(1,2)) if __name__ == '__main__': start = time.time() spider = MaoyanSpider() spider.main() end = time.time() print('執行時間:%.2f' % (end - start))
電影天堂案例(二級頁面抓取)
1、檢視是否為靜態頁面,是否為動態載入
右鍵 - 檢視網頁原始碼
2、確定URL地址
百度搜索 :電影天堂 - 2019年新片 - 更多
3、目標
*********一級頁面***********
1、電影名稱
2、電影連結
*********二級頁面***********
1、下載連結
4、步驟
找URL規律
第1頁 :https://www.dytt8.net/html/gndy/dyzz/list_23_1.html
第2頁 :https://www.dytt8.net/html/gndy/dyzz/list_23_2.html
第n頁 :https://www.dytt8.net/html/gndy/dyzz/list_23_n.html
寫正則表示式
1、一級頁面正則表示式(電影名稱、電影詳情連結)
<table width="100%".*?<td height="26">.*?<a href="(.*?)" rel="external nofollow" rel="external nofollow" .*?>(.*?)</a>
2、二級頁面正則表示式
<td style="WORD-WRAP.*?>.*?>(.*?)</a>
程式碼實現
# decode('gbk','ignore') 注意ignore引數
# 注意結構和程式碼可讀性(一個函式不要太冗餘)
from urllib import request import re import time import random from useragents import * import pymysql class FilmSky(object): def __init__(self): self.url = 'https://www.dytt8.net/html/gndy/dyzz/list_23_{}.html' # 定義兩個物件 self.db = pymysql.connect('127.0.0.1',charset='utf8') self.cursor = self.db.cursor() # 獲取html函式(因為兩個頁面都需要發請求) def get_page(self,url): req = request.Request(url=url,headers={'User-Agent': random.choice(ua_list)}) res = request.urlopen(req) # ignore引數,實在處理不了的編碼錯誤忽略 # 檢視網頁原始碼,發現網頁編碼為 gb2312,不是 utf-8 html = res.read().decode('gbk','ignore') return html # 解析提取資料(把名稱和下載連結一次性拿到) # html為一級頁面響應內容 def parse_page(self,html): # 1. 先解析一級頁面(電影名稱 和 詳情連結) pattern = re.compile('<table width="100%".*?<td height="26">.*?<a href="(.*?)" rel="external nofollow" rel="external nofollow" .*?>(.*?)</a>',re.S) # film_list: [('詳情連結','名稱'),()] film_list = pattern.findall(html) # [('/html/gndy/dyzz/20190806/58956.html','019年驚悚動作《報仇雪恨/血債血償》BD中英雙字幕'),()] ins = 'insert into filmsky values(%s,%s)' for film in film_list: film_name = film[1] film_link = 'https://www.dytt8.net' + film[0] # 2. 拿到詳情連結後,再去獲取詳情連結html,提取下載連結 download_link = self.parse_two_html(film_link) self.cursor.execute(ins,[film_name,film_link]) self.db.commit() # 列印測試 d = {'電影名稱': film_name,'下載連結': download_link} print(d) # {'電影名稱': '019年驚悚動作《報仇雪恨/血債血償》BD中英雙字幕','下載連結': 'ftp://ygdy8:[email protected]:8590/陽光電影www.ygdy8.com.報仇雪恨.BD.720p.中英雙字幕.mkv'} # 解析二級頁面,獲取下載連結 def parse_two_html(self,film_link): two_html = self.get_page(film_link) pattern = re.compile('<td style="WORD-WRAP.*?>.*?>(.*?)</a>',re.S) download_link = pattern.findall(two_html)[0] return download_link # 主函式 def main(self): for page in range(1,11): url = self.url.format(page) html = self.get_page(url) self.parse_page(html) time.sleep(random.randint(1,3)) print('第%d頁完成' % page) if __name__ == '__main__': start = time.time() spider = FilmSky() spider.main() end = time.time() print('執行時間:%.2f' % (end - start))
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。