文章目录
基于协同过滤的电影推荐系统数据集HTML页面分析爬虫代码运行时间百度网盘链接
基于协同过滤的电影推荐系统
用这个数据集实现了一个小型的电影推荐网站,GitHub代码
数据集
数据集是MovieLens提供的ml-latest-small
https://grouplens.org/datasets/movielens/
试了几个数据集,这个数据集效果比较好
10万条评分记录,3600个用户对电影打的标签,9000部电影,600个用户
数据集的格式是这样的
link.csv :存放电影的imdb id和tmdb id
movies.csv :存放电影的id 名称 类型
ratings.csv :用户对电影的评分,范围是0.5~5
tags.csv :用户对电影打的标签
link.csv文件是这样的格式:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200527195828718.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hobXk3Nw==,size_16,color_FFFFFF,t_70)
HTML页面分析
我刚看的时候不明白imdbID是什么意思,后面访问IMBD网站发现,这里的imdbID就是URL里面的标识符 有了link.csv文件里面的imdbID,我们就可以访问到这部电影在IMDB上面的详情页面了(这个数据集也太爽了😄👍) 仔细看这个页面,红框里面是我们需要爬取的信息 ![](https://img-blog.csdnimg.cn/20200527205321557.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hobXk3Nw==,size_16,color_FFFFFF,t_70)
这里就不分析了,不然篇幅有点长了,具体看代码就行。自己可以f12看一下页面的组织结构
爬虫代码
爬虫我用的库是requests和BeautifulSoup,其它库没有用的原因是不会,BS4用起来挺顺手的
需要注意的是,我们爬到的是海报的URL,所以在爬信息的过程中还需要再爬一次,发起请求把海报下载下来。下图中,src存储的就是海报的链接 上述分析过程中可以知道,构造请求应该独立成一个函数,因为第一次爬电影信息要用,第二次爬电影海报要用 下面贴一下代码: 我都是把爬虫包装在一个类里面,这个类的函数结构:
解释一下为什么有white_lst和black_lst这两个奇怪的东西: 下面的爬虫代码我改了很多遍,它的异常处理结构是最后才改好的,也就是说中途会有报错,我需要把bug改好然后继续运行爬虫爬取剩下的电影信息。但是呢,没报错之前已经爬取了一些电影了,我就不需要重头爬了,因此我用一个white_lst来存放已经爬取完成的电影信息。 black_lst是用来存放爬取过程中出错的电影,例如ImdbID失效啊(很少),没有海报信息啊(有几部是这样的),整个数据集爬取完后,再处理这个black_lst里面的电影(最后我发现大概就十部不到的电影出错,于是我就手动处理了) 下图是运行日志中记录的爬取出错的电影 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200527212030776.png)
import requests
from bs4 import BeautifulSoup
import unicodedata
import logging
import csv
import time
class Model():
def __init__(self):
# 请求头
self.headers = {
'User-Agent': 'Mozilla/5.o (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36'
}
# 存放每一步电影的id和imdb的id
self.movie_dct = {}
# 存放已经处理完的movie id
self.white_lst = []
# 电影详情的初始url
self.url = 'https://www.imdb.com/title/'
self.movie_csv_path = '../ml-latest-small/links.csv'
# 海报的保存路径
self.poster_save_path = './poster'
# 电影信息的保存文件
self.info_save_path = './info/info.csv'
# logging的配置,记录运行日志
logging.basicConfig(filename="run.log", filemode="a+", format="%(asctime)s %(name)s:%(levelname)s:%(message)s",
datefmt="%Y-%m-%d %H:%M:%S", level=logging.INFO)
# 表示当前处理的电影
self.cur_movie_id = None
self.cur_imdb_id = None
def get_white_lst(self):
'''获取处理完的白名单'''
with open('white_list') as fb:
for line in fb:
line = line.strip()
self.white_lst.append(line)
def get_movie_id(self):
'''获取电影的id和imdb的id'''
with open(self.movie_csv_path) as fb:
fb.readline()
for line in fb:
line = line.strip()
line = line.split(',')
# 电影id 对应 imdbid
self.movie_dct[line[0]] = line[1]
def update_white_lst(self, movie_id):
'''更新白名单'''
with open('white_list', 'a+') as fb:
fb.write(movie_id + '\n')
def update_black_lst(self, movie_id, msg=''):
with open('black_list.txt', 'a+') as fb:
# 写入movie id 和imdb id,并且加上错误原因
# msg=1是URL失效,msg=2是电影没有海报
fb.write(movie_id + ' ' + self.movie_dct[movie_id] + ' ' + msg + '\n')
def get_url_response(self, url):
'''访问网页请求,返回response'''
logging.info(f'get {url}')
i = 0
# 超时重传,最多5次
while i |