case1: 爬取豆瓣top250排行榜的所有電影的信息
# coding=utf-8# 爬取豆瓣top250排行榜的所有電影的信息:# 1) 下載所有電影的封面,並以電影名命名,保存指定的文件夾中# 2)獲取所有電影的【排名,電影名,導演,主演,年份,國家,類型,評分,評價人數,quote】信息,保存在txt文檔中# 需補充:# 1)加入time模塊,檢查耗時情況和程序運行時間(已加入);# 2)異常情況處理並不怎麼熟悉,在該案例中用的少from urllib.request import urlopenfrom urllib.request import urlretrieveimport reimport osimport chardetimport codecsimport tracebackimport time# *************************** BEGIN: def函數區域 *************************************# 自定義函數創建新文件夾def mkdir(path): # 去除首位空格 path = path.strip() # 去除尾部符號 『\』 path = path.rstrip("") # 判斷路徑是否存在 isExists = os.path.exists(path) # 去掉目錄路徑,返迴文件夾名 fp_new = os.path.basename(path) if not isExists: # 如果不存在,則創建目錄 os.makedirs(path) os.makedirs(path) print(path + 新文件夾 + fp_new + 創建成功) return True else: # 如果目錄存在則不創建 print(path + 文件夾 + fp_new + 已存在) return False# 自定義函數創建新txt文檔def mkfile(fp_abs): f_name = os.path.basename(fp_abs) # 分割出文件名 isexist = os.path.exists(fp_abs) # 判斷路徑下的文件是否存在 if not isexist: # 創建txt文件 txtfile = codecs.open(fp_abs, w, utf-8) # 新建txt文件 print("新文件" + f_name + "已創建完成") return True else: print("新文件" + f_name + "已存在") return False# 下載網頁源代碼def download(html): urlorgs = urlopen(html).read() # 檢測url的編碼格式 char_url = chardet.detect(urlorgs) # print(char_url[encoding]) # print(char_url[encoding]) # {encoding: GB2312, confidence: 0.99, language: Chinese} # url按照對應的編碼格式進行解碼輸出, chardet.detect()內容為key-value字典 request = urlorgs.decode(char_url[encoding]) return request# *************************** END: def函數區域 *****************************************request = download(https://movie.douban.com/top250)# ********************************** BEGIN: 第1步 ***************************************************# 第1步:獲取top250所有分頁的鏈接,並存入txt文檔,文檔命名 top250pagelinks# 新建文件夾top250infomationdir_path = os.path.abspath(".") # 獲取當前路徑 . 當前路徑; .. 上一級路徑dir_new = dir_path + "\top250infomation" # 新目錄路徑及目錄名,作為mkdir函數的傳參mkdir(dir_new) # 創建新文件夾# 新建文檔top250codes.txt,request內容保存至top250codes.txt中,文件保存在新建的文件夾top250infomation中txt_new = "\top250codes.txt"txt_abs = dir_new + txt_newmkfile(txt_abs)# 將request內容保存至top250codes.txt文檔中fp = codecs.open(txt_abs, w, utf-8) # codecs.open()fp.truncate() # 寫入內容之前先清空txt文檔fp.write(request) # 寫入request內容fp.close()# 正則表達式獲取分頁鏈接 pagelinks# reg_plink = rhttps://movie.douban.com/top250reg_plink = r<a.*?filter=" >([d]+)</a>pg_nums = re.findall(reg_plink, request) # [2, 3, 4, 5, 6, 7, 8, 9, 10]page_total = 0page_urls = [] # 存儲所有分頁鏈接的listfor i in range(1, len(pg_nums)+2): num = 25*(i-1) try: page_url = "https://movie.douban.com/top250?start=%d&filter=" %num print("已獲取第%d頁網址" %i +":" + page_url) page_total +=1 page_urls.append(page_url) except: print("分頁網址鏈接獲取出現異常!") breakprint("分頁獲取完成,該網頁下一共有分頁%d個" %i)# page_urls 列錶轉化為字元串,將字元串寫入txt文檔中page_urls_str = "
".join(page_urls)# 新建文檔top250pagelinks.txt,request內容保存至top250pagelinks.txt中,文件保存在新建的文件夾top250infomation中txt_pglink_name = "\top250pagelinks.txt"txt_abs = dir_new + txt_pglink_namemkfile(txt_abs)# 分頁鏈接存入txt文檔中,txt命名:top250pagelinks.txttxt_page_urls_str = open(txt_abs, w) # 打開txt文件,沒有則新建txt; 編碼問題可以用 codecs.open(txt_ol_abs, w, utf-8)txt_page_urls_str.truncate() # 清空txt文件的內容txt_page_urls_str.write(page_urls_str)print("分頁鏈接寫入txt文檔完畢!請知悉!")# ********************************** END: 第1步 ***************************************************# 新建文件夾picdown保存圖片dir_curpath = os.path.abspath(".")dir_imgpath = dir_curpath + "\top250infomation\picdown"mkdir(dir_imgpath)# ********************************** BEGIN: 第2步 *************************************************# 第2步: 獲取電影的圖片:以title命名time.sleep(0.5)print("clock1:%s" % time.clock())# 分頁循環,提取分頁中的相關內容,下載所有top250的imgfor link in page_urls: # print(type(link)) # link str類型 req = download(link) # print(type(req)) # req str類型 # 提取分頁中的<ol>…</ol>標籤內容(電影部分全部信息源代碼),保存在movieol.txt中 reg_ol = re.findall(r<ol.*?</ol>, req, re.S|re.M) # 返回的是list, 索引只有1個 list[0] # print(str(reg_ol[0])) content_ol = str(reg_ol[0]) # 獲取content_ol中的圖片鏈接,並下載圖片至top250infomation中的picdow文件夾中,圖片以title命名 imglinks_org = re.findall(r<img .*?>, content_ol, re.S|re.M) # list for img_info in imglinks_org: try: img_nameorg = re.findall(r<img alt="(.*?)", img_info) # list img_name = img_nameorg[0] + ".jpg" # img_nameorg[0] str img_link = re.findall(r<img.*?src="(.*?)", img_info) # print(type(img_nameorg)) list ; print(type(img_nameorg[0])) str # print(img_nameorg[0], :, img_link[0]) # 無間道 : https://img3.doubanio.com/view/movie_poster_cover/ipst/public/p2233971046.jpg # 搏擊俱樂部 : https://img1.doubanio.com/view/movie_poster_cover/ipst/public/p1910926158.jpg urlretrieve(img_link[0], dir_imgpath + "" + img_name) print("電影封面 《" + img_name[0] + "》 已下載至本地!") except: print("圖片下載出現錯誤!") traceback.print_exc() # traceback模塊查看異常 break time.sleep(0.1)time.sleep(0.5)print("clock2:%s" % time.clock())# ********************************** END: 第2步 *************************************************# ********************************** BEGIN: 第3步 *************************************************# 第3步:獲取電影的具體文本信息# 提取信息:rank, title(/other), information[director, actor, year, country, type], avg_rating, remark_num, quoteError_list = [] # 提取中的錯誤信息先保存在列表中,最後循環完之後寫入txt文檔dic_movie = {} # dic_movie作為info_movie的元素(字典作為list的元素)# 分頁循環,提取分頁中的相關內容for link in page_urls: req = download(link) # 提取分頁中的<ol>…</ol>標籤內容 reg_ol = re.findall(r<ol.*?</ol>, req, re.S | re.M) content_ol = str(reg_ol[0]) # 可以直接 = reg_ol[0](本身為str) # 提取<ol>…</ol>標籤中的<li>…</li>標籤內容,ol中的1個li標籤代表一部電影 content_li = re.findall(r<li>.*?</li>, content_ol, re.S | re.M) # content_li: list # # # <li>…</li>標籤內容循環,分影片信息循環爬取 1個li標籤代表一部電影 for info_li in content_li: # info_li: str # rank rank = re.findall(r(?<=<em class="">)([d]+)(?=</em>), info_li) # list if not rank: # 如果列表為空,則列表中添加元素 "Mistake Occur"; 空列表為FALSE rank.append(Mistake Occur) reminder_error = Mistake Occur: 缺乏「rank」信息! # print(reminder_error) Error_list.append(reminder_error) dic_movie[rank] = rank[0] # title reg_title1 = r<span class="title">(.*?)</span> reg_title2 = r<span class="other">(.*?)</span> title1_org = re.findall(reg_title1, info_li) title2_org = re.findall(reg_title2, info_li) title = [] title2_org = title2_org[0].split( / ) # 字元串有.split()方法 title_org = title1_org + title2_org for i in title_org: i = i.replace( / , ) # 空格佔位符,但是並不等同於空格 title.append(i) if not title: # 如果列表為空,則列表中添加元素 "Mistake Occur"; 空列表為FALSE title.append(Mistake Occur) reminder_error = Mistake Occur: 缺乏「title」信息! # print(reminder_error) Error_list.append(reminder_error) dic_movie[title] = title # information[director, actor, year, country, type] 5個字典作為information這個list的元素 或者直接單獨作為字典元素 bd_org = re.findall(r(?<=<div class="bd">).*?<p class="">(.*?)</p>, info_li, re.S|re.M) content_bd = bd_org[0].replace("
", ) # 去掉換行符 content_bd = bd_org[0].strip() # 去除字元串首尾的空格 # director director = re.findall(r導演: (.*?) , content_bd) if not director: # 如果列表為空,則列表中添加元素 "Mistake Occur"; 空列表為FALSE director.append(Mistake Occur) reminder_error = Mistake Occur: 《 + title[0] + "》 缺乏「導演」信息!" # print(reminder_error) Error_list.append(reminder_error) dic_movie[director] = director[0] # actor actor = re.findall(r主演: (.*?), content_bd) if not actor: actor.append(Mistake Occur) reminder_error = Mistake Occur: 《 + title[0] + "》 缺乏「主演」信息!" # print(reminder_error) Error_list.append(reminder_error) dic_movie[actor] = actor[0] # year, country, type y_c_t = re.findall(r(d+) / (.*?) / (.+), content_bd) # [(2009, 澳大利亞, 劇情 動畫)] dic_movie[year] = y_c_t[0][0] dic_movie[country] = y_c_t[0][1] dic_movie[type] = y_c_t[0][2] # print(dic_movie) # avg_rate info_li中匹配 avg_rate = re.findall(r<span class="rating_num".*?>(.*?)</span>, info_li, re.S|re.M) if not avg_rate: avg_rate.append(Mistake Occur) reminder_error = Mistake Occur: 《 + title[0] + "》 缺乏「評分」信息!" # print(reminder_error) Error_list.append(reminder_error) dic_movie[avg_rate] = avg_rate[0] # quote_num info_li中匹配 quote_num = re.findall(r(?<=<div class="star">).*?<span>(d+).*?(?=/span), info_li, re.S|re.M) if not quote_num: quote_num.append(Mistake Occur) reminder_error = Mistake Occur: 《 + title[0] + "》 缺乏「評論人數」信息!" # print(reminder_error) Error_list.append(reminder_error) dic_movie[quote_num] = quote_num[0] # quote info_li中匹配 quote = re.findall(r(?<=<p class="quote">).*?>(.*?)(?=</span>), info_li, re.S|re.M) if not quote: quote.append(Mistake Occur) reminder_error = Mistake Occur: 《 + title[0] + "》 缺乏「一句話評論」信息!" # print(reminder_error) Error_list.append(reminder_error) dic_movie[quote] = quote[0] # dic_movie直接作為list元素,傳入info_movie = []單個電影list中, 有問題,故直接將dic_movie寫入txt文檔 # 需要轉化為list的話,從文本中讀取出來, str轉list # dic_movie追加寫入txt文檔中: top250_dic_movie.txt (循環追加寫入) txt_dic_movie = codecs.open(top250_dic_movie.txt, a, utf-8) txt_dic_movie.write(str(dic_movie) +
) txt_dic_movie.close() time.sleep(0.1)time.sleep(0.5)print("clock3:%s" % time.clock())# ********************************** END: 第3步 *************************************************# ********************************** Error_log *************************************************# 新建txt文檔,Error_log.txt, 保存信息提取中出現的錯誤信息提示語句txt_errorlog = codecs.open(Error_log.txt, w, utf-8) # 以utf-8編碼新建/打開txt文檔# list中的內容寫入txt中(採用方法2):# 方法1: 循環追加寫入,a;# 方法2: list內容
.join(list), 字元串直接寫入info_error =
.join(Error_list) # list轉為str, str更方便寫入txt文檔txt_errorlog.truncate()txt_errorlog.write(info_error)txt_errorlog.close()# ********************************** Error_log *************************************************# ********************************** 讀取txt文檔內容 *************************************************# top250_dic_movie.txt文檔中的內容提取出來,保存在列表info_movies中# 讀取txt文件info_movie = []content_txtfile = codecs.open(top250_dic_movie.txt, r, utf-8)content_read = content_txtfile.readlines() # .readlines()方法for line in content_read: line = line.strip() # 可以去掉換行符
info_movie.append(line) # 所有dic格式保存的電影信息讀取至列表info_movie中# print(info_movie)print("文檔讀取進度:top250_dic_movie.txt文檔中的內容已經全部讀取至列表info_movie中!")# ********************************** 讀取txt文檔內容 *************************************************print("clock4:%s" % time.clock())print(程序運行結束!)
推薦閱讀:
※基於 Gensim 的 Word2Vec 實踐
※Python 會不會替代 MATLAB?
※薦書:《Fluent Python》
※Python|Arcgis|交通時距圈
※10分鐘python圖表繪製 | seaborn入門(四):回歸模型lmplot