0
点赞
收藏
分享

微信扫一扫

Python模块selenium实例:电影分类排名数据生成json,sqlite和excel(openpyxl)文件(二)

影子喵喵喵 2022-05-04 阅读 60

前面一篇文章已经生成了每个类别的电影评分前100位的json文件共21个。如下图:
在这里插入图片描述
现在我想把所有的电影按照评分做成一个总表。为此需要逐个打开每个文件,这里要用到os模块的listdir方法,如下建立一个遍历文件的获取文件名的函数:

from os import listdir


def movie_files(folder):
    """gather list of image files"""

    movie_files = []
    for f in listdir(folder):       
        if f.endswith("json"):
            movie_files.append(f)
    return movie_files

函数中folder参数为文件所在目录,通过for循环遍历文件夹,如果文件以json结尾的则把文件名添加到列表,最后返回列表。
我们有了文件的名字列表后,现在需要逐个打开然后把数据添加到新的列表,函数如下:

def grand_data(folder,movieFiles):
    """Granded the data from the genre movies"""

    movieDataScore = []
    movieDatas = []
    for file in movieFiles:
        with open(folder+file, 'r',encoding='utf-8') as f:
            movies = json.load(f)  
            for m in movies:
                movieDataScore.append(m['IMDb Score']) 
                movieDatas.append(m)

    # Sorted the IMDb score list and remove duplicates 
    new_movieDataScore = sorted(list(set(movieDataScore)),reverse=True)

    return movieDatas,new_movieDataScore

需要注意的是,我们建立了两个列表,一个把所有类别的电影数据放进去,另外一个要把电影评分放进去,同时通过set去重后再转为列表进行排序,函数最后返回两个列表。

数据有了就要重新对数据进行排列和清洗,有些电影是在不同的类别里都有出现的,所有要去掉重复的,同时按分数排序,函数如下:

def movie_datas(movieDatas,new_movieDataScore):
    """Sorted the dict according to IMDb score"""

    final_movieDatas = []
    cnt = 0
    movieNames = []
    while cnt < len(movieDatas):
        for n in new_movieDataScore:
            for movie in movieDatas:
                if n == movie['IMDb Score']:                    
                    if movie['Movie'] not in movieNames:# fix duplicate data
                        movieNames.append(movie['Movie'])
                        final_movieDatas.append(movie)
                    cnt += 1
    return final_movieDatas

通过while循环来对数据进行清洗,首先遍历通过分数列表依次找到从高到低分数,然后再遍历电影数据找到匹配分数的电影,同时通过条件句排除重复电影。最后返回最终列表。
最后把数据写入json文件:

def movie_json_data(final_movieDatas):
    """Generate the json data"""
    with open('json_data/top_movies.json', 'w',encoding='utf-8') as json_file:
            json.dump(final_movieDatas, json_file, indent=4, ensure_ascii=False)

这样我们所有想要的数据都已保存成json文件,这就为我们之后创建sqlite和excel创造了便利。

下面开始创建sqlite数据库,新建一个MoviesSqlite.py文件,首先我们还是要遍历文件夹获取所有的文件名,这里可以建立一个函数也可以引用上一个文件中的函数,这里就略过了,直接开始建立sqlite库。
方法还是之前文章中介绍过的方法,需要注意的是我们需要每个类别对应建立一个表格,所以我们会把建表部分放入for循环中,整个函数如下:

def sqlite_data(folder,movieFiles):

    conn = sqlite3.connect('sqliteData/moviesSsqData.sqlite')    
    for movieFile in movieFiles:
        filename = movieFile.split('.')[0][0:-5]
        cur = conn.cursor()

        # Make table using executescript()
        cur.executescript('''        
        DROP TABLE IF EXISTS  '''+ filename + ''';'''+ '''
        
        CREATE TABLE ''' + filename + ''' (
            id     INTEGER NOT NULL PRIMARY KEY 
                    AUTOINCREMENT UNIQUE,
            Rank            INTEGER,
            Movie           INTEGER,
            Year            INTEGER,
            Duration        INTEGER,
            MovieGenres     INTEGER,
            IMDbScore       INTEGER,
            Metascore       INTEGER,
            Plot            INTEGER,
            Director        INTEGER,
            Stars           INTEGER,
            Votes           INTEGER,
            Gross           INTEGER
        );
        ''')

        with open(folder+movieFile, 'r',encoding='utf-8') as f:
            json_data =  json.load(f)
        
        
        for entry in json_data:
            Rank = entry['Rank']         
            Movie = entry['Movie']   
            Year  = entry['Year']          
            Duration = entry['Duration']       
            MovieGenres = entry['Movie Genres']  
            IMDbScore = entry['IMDb Score']  
            Metascore = entry['Metascore'] 
            Plot = entry['Plot']   
            Director = entry['Director']  
            Stars = entry['Stars']
            Votes = entry['Votes'] 
            Gross = entry['Gross']

            # Print data
            cur.execute('''INSERT OR IGNORE INTO ''' + filename + ''' (Rank,Movie,Year,
            Duration,MovieGenres,IMDbScore,Metascore,Plot,
            Director,Stars,Votes,Gross)
                    VALUES ( ?,?,?,?,?,?,?,?,?,?,?,? )''', (
                    Rank,Movie,Year,Duration,MovieGenres,IMDbScore
                    ,Metascore,Plot,Director,Stars,Votes,Gross))
            conn.commit()

需要注意的点是我们通过’‘’
DROP TABLE IF EXISTS ‘’‘+ filename + ‘’’;‘’'这个参数传递的方式赋予sqlite表格名称。最后生成的数据库如下图所示:
在这里插入图片描述
终于到了最后一部分,也是使用新的模块的一部分,在此我们用openpyxl模块来创建excel文件。

首先的建立一个moviesExcel.py文件,同样我们需要遍历文件夹,这里不再赘述了,直接进入主题。
我们不单单把数据写入excel,同时我还想设置下格式及样式,我们先导入相关模块:

import openpyxl
from openpyxl.styles import PatternFill, Alignment, Font

首先我们想写入数据,因为我们有不同类别及汇总,所以我们依然把创建表格部分放入for循环,函数如下:

def excel_data(folder,savedir,movieFiles):
    """Generate the excel"""
    
    # Creat excel
    movie_book = openpyxl.Workbook()
    cnt = 0

    for movie in movieFiles:
        mvName = movie.split('.')[0]
        #Creat sheet according to movie's genre
        if mvName != "top_movies":
            sheet = movie_book.create_sheet(index=cnt,title=mvName)
            cnt += 1             
        else:
            sheet = movie_book.create_sheet(index=0,title='top_movies')
        
        # Open the json data
        with open(folder+movie,'r',encoding='utf-8') as f:
                json_data =  json.load(f)
                        
        # Title data and the width of per colum
        sheet['A1'] = 'Rank'
        sheet.column_dimensions['A'].width = 7
        sheet['B1'] = 'Movie'
        sheet.column_dimensions['B'].width = 30
        sheet['C1'] = 'Year'
        sheet.column_dimensions['C'].width = 7
        sheet['D1'] = 'Duration'
        sheet.column_dimensions['D'].width = 15
        sheet['E1'] = 'Movie Genres'
        sheet.column_dimensions['E'].width = 15
        sheet['F1'] = 'IMDb Score'
        sheet.column_dimensions['F'].width = 15
        sheet['G1'] = 'Metascore'
        sheet.column_dimensions['G'].width = 15
        sheet['H1'] = 'Plot'
        sheet.column_dimensions['H'].width = 100
        sheet['I1'] = 'Director'
        sheet.column_dimensions['I'].width = 20 
        sheet['J1'] = 'Stars'
        sheet.column_dimensions['J'].width = 30
        sheet['K1'] = 'Votes'
        sheet.column_dimensions['K'].width = 12
        sheet['L1'] = 'Gross'
        sheet.column_dimensions['L'].width = 12

        # Print Data 
        row = 2
        for entry in json_data:
            sheet.row_dimensions[row].height = 35
            sheet.cell(column=1, row=row, value=entry['Rank'])

            # Add hyperlink to movie's name        
            sheet.cell(column=2, row=row,).value ='=HYPERLINK("{}","{}")'.format('https://www.douban.com/search?q={}'.format(entry['Movie']),entry['Movie'])   
            sheet.cell(column=2, row=row,).font = Font(u'single', size=9,color='003366FF')
            
            sheet.cell(column=3, row=row, value=entry['Year'])
            sheet.cell(column=4, row=row, value=entry['Duration'] )
            sheet.cell(column=5, row=row, value=entry['Movie Genres'])
            sheet.cell(column=6, row=row, value=entry['IMDb Score'])
            sheet.cell(column=7, row=row, value=entry['Metascore'] )
            sheet.cell(column=8, row=row, value=entry['Plot'])
            sheet.cell(column=9, row=row, value=entry['Director'])
            sheet.cell(column=10, row=row, value=entry['Stars'])        
            sheet.cell(column=11, row=row, value=entry['Votes'])  
            sheet.cell(column=12, row=row, value=entry['Gross'] )
            row += 1

    movie_book.save(savedir+'moviesExcelData.xlsx')

展开解释下,开始部分通过条件句把汇总表格放到第一个。然后我们建立表头, sheet[ ]通过指定单元格写入内容,同时我们通过sheet.column_dimensions[].width调整相应的单元格的宽度。接下来通过一个循环写入数据,第一行是我们的表头,所以我们第二行开始写入,因此row默认值设为2,写入数据前同样通过sheet.row_dimensions[row].height方法指定单元的高度。在这里我们通过sheet.cell(column=1, row=row, value=value)方法写入数据,column为列,row为行,value为写入内容。

大家应该也注意到了,电影名部分我们通过=HYPERLINK指定单元格为超链接,这样我们点击电影名它会跳转到相关网页,这里用的豆瓣,直接传递电影名显示搜索结果,要注意搜出来的电影有可能会有出入,大家可以通过时长或者内容对一下,有些豆瓣可能都木有相关信息的。同时我们把电影名单元格字体颜色通过font指定为浅蓝色提示其为超链接。

这样我们的excel建立好了,但是呢并不好看,我决定再调整下格式,函数如下:

def excel_style(sheet,rows):
    """Setting the format of the excel"""

    sheet.freeze_panes = 'C2'# freeze the panes (C2 represent that freeze row1 and columnA&coulumnB)
    bgcolor = PatternFill('solid', fgColor='00808080')# Backgraound color 
    font = Font(u'微软雅黑', size=11, bold=True, italic=False, strike=False, color='00333333')
    # ord = 65
    for col in range(1, 13):
       sheet.cell(column=col, row=1, value="").fill = bgcolor
       sheet.cell(column=col, row=1, value="").font =font

    bgcolor_text1 = PatternFill('solid',fgColor='00C0C0C0')
    bgcolor_text2= PatternFill( 'solid',fgColor='00969696')	
    font_text = Font(u'微软雅黑', size=9,color='00333333')

    for r in range(2,rows+2):
        for col in range(1, 13):
            if r % 2 == 0:
                sheet.cell(column=col, row=r, value="").fill = bgcolor_text1
            else:
                sheet.cell(column=col, row=r, value="").fill = bgcolor_text2
            sheet.cell(column=col, row=r, value="").font = font_text
            # Word wrap and Location
            sheet.cell(column=col, row=r, value="").alignment = Alignment(horizontal='left',vertical='center',wrapText=True)

关键部分我做了英文注释,但是还是稍微解释下,通过sheet.freeze_panes冻结窗口,这里指定C2指的是A和B列及第1行被冻结。然后设置背景色和字体格式,
通过 PatternFill设置背景色的参数,第一个参数为填充样式。然后通过.fill赋予单元格。字体类似首先通过FONT设置参数,.font赋予单元格。第一个循环是第一行表头赋予一个较深的背景色,然后第二个循环会有两个背景色相互交替,从而使表格更容易查看。(这里的字体样式和背景色都是按个人喜好来设置的,大家可以随意设置自己中意的样式。)
.alignment = Alignment(horizontal=‘left’,vertical=‘center’,wrapText=True) 设置的是单元格内文本的位置,我设置的是靠左(horizontal),上下居中(vertical)及自动换行(wrapText=True)。
创建表格的函数中每个表格都需要样式,所以把样式函数放进创建函数内(第一个for循环内)执行:

		# Format        
        rows = len(json_data)
        excel_style(sheet,rows)

生成的excel表格如下:

至此我们的这个练习实列就完成了,希望能给大家些微的思路和帮助,共同学习进步,谢谢!

举报

相关推荐

0 条评论