赞
踩
✨作者主页:IT研究室✨
个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。
☑文末获取源码☑
精彩专栏推荐⬇⬇⬇
Java项目
Python项目
安卓项目
微信小程序项目
随着互联网的普及和信息技术的快速发展,人们对于娱乐和阅读的需求越来越高。小说作为人们普遍喜欢的文学形式之一,其阅读量和影响力不容忽视。因此,建立一个高效、智能的小说推荐系统具有十分重要的意义。本课题基于当前小说推荐领域的现状和问题,旨在开发一个集成了爬虫技术、可视化技术和协同过滤算法的小说推荐系统,以满足用户对于小说信息获取和个性化推荐的需求,同时提高小说推荐的质量和效率。
当前的小说推荐系统大多数都采用了基于内容的推荐方法,这种方法主要基于用户过去的行为和偏好来推荐相似的小说。然而,这种推荐方法存在着一些问题。首先,它无法有效地发现和推荐一些新的、潜在的热门小说。其次,它对于用户偏好的理解不够深入,无法真正做到个性化的推荐。最后,由于数据稀疏性问题,推荐结果往往存在着偏差,无法做到真正的精准推荐。
本课题所研究的小说推荐系统,将通过爬虫技术从各大小说网站爬取数据,并利用可视化技术将数据呈现给用户。同时,系统将采用协同过滤算法,根据用户的历史行为和偏好,以及其他用户的评价和行为,进行深度学习和模型训练,最终为用户提供更加个性化、精准的小说推荐。
本课题的研究目的在于解决当前小说推荐领域存在的问题,提高推荐质量和效率,为用户提供更加个性化、精准的小说推荐服务。同时,通过可视化技术和协同过滤算法的应用,帮助用户更好地理解小说内容和用户群体的喜好,提高用户的阅读体验和满意度。
本课题的研究具有重要的理论和实践意义。首先,通过研究和实践,可以进一步完善和发展小说推荐领域的技术和方法,推动该领域的发展和创新。其次,课题的研究成果可以帮助各大小说网站提高服务质量,增加用户粘性和活跃度,提高网站的影响力和收益。此外,本课题的研究还可以为其他领域的个性化推荐提供参考和借鉴,推动相关领域的发展。
def toSplitShowWordFont(tem: str, splitKey: str) -> list[str]: """ 从 tem 切割字符,切割关键字为 spaceWork :param tem: 需要被切割的字符 :param splitKey: 切割关键字 :return: 切割完成的列表 """ result: list[str] = [] if tem is None: return None currentStr = tem.rstrip() if currentStr == "": return None temSpaceArray = currentStr.split(splitKey) for spaceWork in temSpaceArray: currentStr = spaceWork.rstrip() if currentStr == "": continue result.append(currentStr) if len(result) == 0: return None return result def toShowWordFont(tem: str) -> list[str]: result: list[str] = [] if tem is None: return None tem = tem.rstrip() if tem == "": return None spaceArray = toSplitShowWordFont(tem, " ") if spaceArray is not None: for itemSpace in spaceArray: tabArray = toSplitShowWordFont(itemSpace, "\t") if tabArray is not None: for itemTab in tabArray: enterArray = toSplitShowWordFont(itemTab, "\n") if enterArray is not None: for itemEnter in enterArray: result.append(itemEnter) return result def initIgnore(argvMaps: typing.Dict[str, typing.List[str]]) -> typing.Union[None, typing.List[str]]: """ 初始化一个忽略参数 """ igList0 = argvMaps.get("i") igList1 = argvMaps.get("ig") igList2 = argvMaps.get("ignore") resultBuffList: typing.List[str] = [] if igList1 is not None: for arg in igList1: spriteName = requestNovelsLib.getBaseFileName(arg, checkFileSuffix=".py").upper() resultBuffList.append(spriteName) if igList2 is not None: for arg in igList2: spriteName = requestNovelsLib.getBaseFileName(arg, checkFileSuffix=".py").upper() resultBuffList.append(spriteName) if igList0 is not None: for arg in igList0: spriteName = requestNovelsLib.getBaseFileName(arg, checkFileSuffix=".py").upper() resultBuffList.append(spriteName) if len(resultBuffList) == 0: return None return resultBuffList def getTargetAbsFilePath(rootPath: str, fileSuffix: str = None) -> list[str]: """ 获取目录下的所有指定的后缀名,返回的是绝对路径 :param rootPath: 根目录 :param fileSuffix: 后缀 :return: 匹配的后缀文件名 """ result: list[str] = [] if not os.path.exists(rootPath): return None if fileSuffix is not None and len(fileSuffix) == 0: fileSuffix = None if fileSuffix is not None and fileSuffix[0] != '.': fileSuffix = f".{fileSuffix}" buffSubResult: list[str] = None buffPath: str = None fileOrDirs = requestNovelsLib.getTargetInDirAbsFilePath(rootPath) for fileOrDir in fileOrDirs: if os.path.isfile(fileOrDir): if fileSuffix is not None: if fileOrDir.endswith(fileSuffix) == 1: result.append(fileOrDir) else: result.append(fileOrDir) return result def getRunPyScripts(runScriptNameArgs: list[str], ignorePyNames: list[str]) -> list[str]: """ 运行指定的模块 :param runScriptNameArgs: 是否运行模块, 非空表示运行,若需要指定运行,则需要输入匹配的模块名称 :param ignorePyNames: 忽略的模块名称 """ runScriptFilesPath = [] ignore = False buff = [] buffRunScriptFilesPath = requestNovelsLib.getTargetInDirAbsFilePath(requestNovelsLib.getCallAbsDirPath()) ## 获取所有 .py 结尾 for fileItem in buffRunScriptFilesPath: if fileItem.endswith(".py"): buff.append(fileItem) buffRunScriptFilesPath = buff if runScriptNameArgs is not None: ## 获取需要运行的 if len(runScriptNameArgs) != 0: for pythonName in runScriptNameArgs: basePythonName = requestNovelsLib.getBaseFileName(pythonName).upper() for fullPath in buff: baseName = requestNovelsLib.getBaseFileName(fullPath).upper() if baseName == basePythonName: runScriptFilesPath.append(fullPath) else: runScriptFilesPath = buffRunScriptFilesPath ## 获取所有忽略的 if ignorePyNames is not None: buff = [] buffRunScriptFilesPath = [] for image in ignorePyNames: buff.append(requestNovelsLib.getBaseFileName(image).upper()) ignore = True for fileAllName in runScriptFilesPath: ignore = False pyBaseName = requestNovelsLib.getBaseFileName(fileAllName).upper() for compIgnore in buff: if compIgnore == pyBaseName: ignore = True break if not ignore: buffRunScriptFilesPath.append(fileAllName) runScriptFilesPath.clear() for pyFile in buffRunScriptFilesPath: name = requestNovelsLib.getBaseFileName(pyFile) path = requestNovelsLib.getTargetAbsSavePath(pyFile) improtMode = importlib.util.find_spec(name, path) if improtMode is not None: modeResult = improtMode.loader.load_module() for getDir in dir(modeResult): if getDir == "modeRequestGetUrl": runScriptFilesPath.append(pyFile) break return runScriptFilesPath buffRunScriptFilesPath = [] for pyFile in runScriptFilesPath: name = requestNovelsLib.getBaseFileName(pyFile) path = requestNovelsLib.getTargetAbsSavePath(pyFile) improtMode = importlib.util.find_spec(name, path) if improtMode is not None: modeResult = improtMode.loader.load_module() for getDir in dir(modeResult): if getDir == "modeRequestGetUrl": buffRunScriptFilesPath.append(pyFile) break return buffRunScriptFilesPath class Pari: def __init__(self, key, value): self.key = key self.value = value def runTargetScriptsModeAtThread(filePath): modeName = requestNovelsLib.getBaseFileName(filePath) print(f"=================> 运行 {modeName} <=========") model = requestNovelsLib.getPathPythonModels(filePath) if model is None: return None try: model.modeRequestGetUrl() except: traceback.print_exc() print(f"=================> 执行完毕 {modeName} <=========") return model def getFileFindKeyWords(filePath: str, pythonScriptPath: str, cutterStr: str) -> list[str]: """ 查找文件关键字 @param filePath: 文件路径 @param pythonScriptPath: 脚本路径 @param cutterStr: 分割字符串 @return: 文件中的关键字列表 """ ## 获取文件内容 try: print(f"获取 {filePath} 路径关键字") if os.path.isfile(filePath): absFilePath = requestNovelsLib.getTargetInDirAbsFilePath(filePath) if len(absFilePath) == 0: return [] conent = requestNovelsLib.readFile(absFilePath[0]) return conent.upper().replace("\ufeff", "").split(cutterStr) filesContenMap = requestNovelsLib.readDirFiles(filePath) resultList: list[str] = [] for fileFullPathName, fileConten in filesContenMap.items(): replactConten = fileConten.upper().replace("\ufeff", "").split(cutterStr) for key in replactConten: newKey = key.strip() if len(newKey) != 0: resultList.append(newKey) return resultList except: traceback.print_exc() return [] def initFindKeys(kOption: list[str], fOption: list[str], fOptionFileCutterStr: str = None) -> typing.Dict[str, list[str]]: """ 获取所有关键字,他不允许使用 py 后缀来指定关键字文件 @param kOption: k 选项关键字,由命令行提供 @param fOption: f 选项文件/文件夹,由命令行提供,该函数会读取所有匹配的文件或文件夹 @param fOptionFileCutterStr: 文件内容的切分符 @return: 路径映射到关键字的配对,可以参考路径来实现相对存放,-k 选项发挥为 “” """ ## 处理空的非法分隔符 if fOptionFileCutterStr is None or len(fOptionFileCutterStr) == 0: fOptionFileCutterStr = '\n' else: fOptionFileCutterStr = fOptionFileCutterStr.replace("\\t", '\t').replace("\\n", '\n') result: typing.Dict[str, list[str]] = {} currentPath = requestNovelsLib.getCallAbsDirPath() global __PoolCount with multiprocessing.Pool(__PoolCount) as processPool: ## 存储进程返回 processRunTimeObjMap: Dict[str, multiprocessing.pool.ApplyResult] = {} ## 遍历所有文件 for argFilePath in fOption: if not argFilePath.endswith("py"): processRunTimeObjMap[argFilePath] = processPool.apply_async(getFileFindKeyWords, (argFilePath, currentPath, fOptionFileCutterStr,)) ## 终止进程分配 processPool.close() ## 配置 -k 选项 if kOption is not None and len(kOption): kOptionFileName = requestNovelsLib.getPathName(__file__) buffHumanNameList = [] for keyWord in kOption: for humanNames in requestNovelsLib.getHumanNameList(keyWord): buffHumanNameList.append(humanNames) ## 缩短字符串 buffHumanNameList = requestNovelsLib.strListAtStrip(buffHumanNameList, 0) buffHumanNameList = requestNovelsLib.strListToChange(buffHumanNameList, True) buffHumanNameList = requestNovelsLib.strListreduce(buffHumanNameList) result[kOptionFileName] = requestNovelsLib.removeRepeateUnity(buffHumanNameList) ## 等待所有进程 processPool.join() resulitItems = processRunTimeObjMap.items() for filePath, processPoolResult in resulitItems: buffHumanNameList = [] for keyWord in processPoolResult.get(): for humanNames in requestNovelsLib.getHumanNameList(keyWord): buffHumanNameList.append(humanNames) buffHumanNameList = requestNovelsLib.strListAtStrip(buffHumanNameList, 0) buffHumanNameList = requestNovelsLib.strListToChange(buffHumanNameList, True) buffHumanNameList = requestNovelsLib.strListreduce(buffHumanNameList) arrayList = requestNovelsLib.removeRepeateUnity(buffHumanNameList) if len(arrayList) != 0: result[filePath] = arrayList return result def findNovelExisKey(findNovelInfo: requestNovelsLib = None, keys: list[str] = None) -> str: """ 判断是否存在关键字 @param findNovelInfo: 判断对象 @param keys: 关键字列表 @return: 存在返回 关键字,否则返回 None """ upName = findNovelInfo.novelName.upper() upInfo = findNovelInfo.info.upper() upLastItem = findNovelInfo.lastItem.upper() upAuthor = findNovelInfo.author.upper() for key in keys: if upName.find(key) != -1 or upInfo.find(key) != -1 or upLastItem.find(key) != -1 or upAuthor.find(key) != -1: if len(findNovelInfo.attFlide) > 0: findNovelInfo.attFlide = f"{findNovelInfo.attFlide}\n\t关键字: {key}" else: findNovelInfo.attFlide = f"关键字: {key}" return key return None def fromDbGetNovelInfo(dbPath: str, findObjs: list[requestNovelsLib.NovelInfo], iniFilePath, keys, runScrictPath, targetTopDirPath, allKeyIngFilePath, inKeyIngFilePath, oldIngFilePath, userMakeName=False) -> dict[str, Pari]: """ 查找匹配的小说内容 @param dbPath: db 路径 @param findObjs: 所有的小说信息 @param iniFilePath: 配置文件路径 @param keys: 查找的关键字 @param runScrictPath: 脚本运行的路径 @param targetTopDirPath: 顶部文件夹(带路径) @param allKeyIngFilePath: 全匹配过滤路径 @param inKeyIngFilePath: 存在配过滤路径 @param oldIngFilePath: 已经查找到的小说文件路径 @param userMakeName: 是否使用标记 @return: 已经匹配好的对象, [路径,[关键字,小说对象]] """ if iniFilePath != "": iniFileBaseName = requestNovelsLib.getPathName(iniFilePath) dbBaseName = requestNovelsLib.getBaseFileName(requestNovelsLib.getPathName(dbPath)) targetDir = f"{runScrictPath}{os.sep}{targetTopDirPath}{os.sep}{iniFileBaseName}{os.sep}{dbBaseName}" targetFilePath = "" ## 删除已经存在的文件 # if os.path.exists(targetDir): # requestNovelsLib.removePath(targetDir) ## 返回列表 resultDict: dict[str, Pari] = {} ## 遍历所有对象 ingKey: str = "" ## 过滤不需要的小说 oldNovelName: list[str] = [] if userMakeName: lock = requestNovelsLib.getMultiProcessDBLock() try: lock.acquire() oldNovelName = requestNovelsLib.readFile(oldIngFilePath).split("\n") oldNovelName = requestNovelsLib.strListRmoveSpace(oldNovelName, False, 0) finally: lock.release() ## 过滤配置文件 findObjs = requestNovelsLib.filterListNovel(findObjs, allKeyIngFilePath, inKeyIngFilePath, appendAllKeyList=oldNovelName) writeListNovelName: list[str] = [] try: noveName = "" for findNovelInfo in findObjs: exisKeyWork = findNovelExisKey(findNovelInfo, keys) if exisKeyWork: targetFilePath = f"{targetDir}{os.sep}{findNovelInfo.novelTypeName}.txt" resultPari = resultDict.get(targetFilePath) if resultPari is None: resultPari = Pari(keys, []) resultDict[targetFilePath] = resultPari resultPari.value.append(findNovelInfo) except: msg = f"查找异常({dbPath})\n {traceback.format_exc()}" sys.stderr.write(msg) requestNovelsLib.writeLogFile(msg, httpUrl="find novel error") for file, pair in resultDict.items(): pair.value = requestNovelsLib.novelInfoTypeSort(requestNovelsLib.removeNovelsRepeatAtUrl(pair.value)) return resultDict return {} def getFindKeyInfo(keyFindMap: dict[str, list[str]], dbFilePaths: list[str], currentTimeStr: str, userMakeName=False) -> dict[str, list[requestNovelsLib.NovelInfo]]: """ 获取所有匹配的小说 @param keyFindMap: 路径与查找关键字的匹配 @param dbFilePaths: 请求的 db 文件路径,包含所有的 db @param currentTimeStr: 当前时间的字符串格式 @param userMakeName: 是否使用记录标记 @return: 已经匹配好的小说列表 """ dbFilePaths = requestNovelsLib.removeRepeateUnity(dbFilePaths) if len(dbFilePaths) == 0: return {} poolResultObjList = [] scriptPath = f"{requestNovelsLib.getCallAbsDirPath()}" result: dict[str, list[requestNovelsLib.NovelInfo]] = {} global __PoolCount with multiprocessing.Pool(__PoolCount) as processPool: allKeyIngFilePath = f"{requestNovelsLib.getCallAbsDirPath()}/out/ini/jumpOut.ini" inKeyIngFilePath = f"{requestNovelsLib.getCallAbsDirPath()}/out/ini/filter.ini" novels: list[requestNovelsLib.NovelInfo] = [] ## 获取数据库内容 for dbPath in dbFilePaths: novels = requestNovelsLib.outputSqlite3(dbPath) print("\n===") dbFileCount = 0 for filePath, initKeys in keyFindMap.items(): dbFileCount += 1 iniFileBaseName = requestNovelsLib.getPathName(filePath) dbBaseName = requestNovelsLib.getBaseFileName(requestNovelsLib.getPathName(dbPath)) oldIngFilePath = f"{requestNovelsLib.getCallAbsDirPath()}/out/ini/ingFindInDBFiles/{dbBaseName}.ini" print(f"在《{dbBaseName}》中匹配 -《{iniFileBaseName}》- 文件保留的关键字 => 配置文件计数 : {dbFileCount}") poolResultObjList.append(processPool.apply_async(fromDbGetNovelInfo, (dbPath, novels, filePath, initKeys, scriptPath, "out/find", allKeyIngFilePath, inKeyIngFilePath, oldIngFilePath, userMakeName))) print("\n===") ## 关闭资源 processPool.close() ## 等待结束 processPool.join() for processResult in poolResultObjList: for writePathFileName, resultNovelsPair in processResult.get().items(): exisNovelsPair = result.get(writePathFileName) if exisNovelsPair is None: result[writePathFileName] = resultNovelsPair else: for saveNovel in resultNovelsPair.value: exisNovelsPair.value.append(saveNovel) return result def writeFindResultNovels(wirteDict: dict[str, Pari] = None): """ 把查找到的小说写入文件 @param wirteDict: 内容映射,从文件到小说内容的映射 """ if wirteDict is None: return allLen = 0 lens = 0 writeFileCount = 0 keyCount = 0 removeDirList = [] for file, pair in wirteDict.items(): ## 是否删除文件夹内的所有内容 fileDirPath = requestNovelsLib.getTargetAbsSavePath(file) fileBaseName = os.path.basename(fileDirPath) fileDirPath = fileDirPath[0: len(fileDirPath) - len(fileBaseName)] lens = 0 for dirPath in removeDirList: if dirPath == fileDirPath: lens = 1 break if lens == 0: removeFileList = requestNovelsLib.removePath(fileDirPath) print(f"\n删除目录 {fileDirPath} (文件夹与文件)数量 : {len(removeFileList)}") removeDirList.append(fileDirPath) lens = len(pair.value) keyCount = len(pair.key) allLen += lens requestNovelsLib.writeFile(f"{requestNovelsLib.toStr(pair.value)}\nkey = {', '.join(pair.key)}\n关键字 : {keyCount}\n已经查找到小说数量 : {lens}\n", file, "w") writeFileCount += 1 print(f"文件=> {file} 写入 {lens} 个小说,关键字为 {keyCount} 个, 第 {writeFileCount} 个文件") print(f"共存在 => {allLen}, 写入文件数量 : {writeFileCount}") if __name__ == '__main__': print(f"正在从 {requestNovelsLib.currentCallThisFunctionFileName()} : {requestNovelsLib.currentCallThisFunctionFileLine()} 行 开始执行代码") ## 当前时间的字符串 currentTimeStr = datetime.datetime.now().strftime(f'%d_%H_%M_%S') ## 查找配置文件 -f runFindCmdKeyFileList = [] ## 查找关键字 -k ## 以 空格 为分隔符的关键字 spaceSplitKeyWork = "" ## 以 元素 为单位的关键字 runFindCmdKeyList = [] if spaceSplitKeyWork is not None and spaceSplitKeyWork != "": showWordArray = toShowWordFont(spaceSplitKeyWork) if showWordArray is not None: for x in showWordArray: runFindCmdKeyList.append(x) ## 去掉重复 runFindCmdKeyList = requestNovelsLib.removeRepeateUnity(runFindCmdKeyList) ## 填充脚本目录到查找列表 argvDict = {'f': runFindCmdKeyFileList, 'k': runFindCmdKeyList} ## 初始化查找信息 paramArgs = requestNovelsLib.initParamArgs(argvDict) ## 初始化忽略参数 ignorePyNames = initIgnore(argvDict) ## 存在 get 参数则开始运行爬虫 getArgs = argvDict.get("get") ## 删除重复 ignorePyNames = requestNovelsLib.removeRepeateUnity(ignorePyNames, 0, 0) if getArgs is not None: ## 脚本代理运行 runScritpList = getRunPyScripts(getArgs, ignorePyNames) if len(runScritpList) > 0: with ThreadPoolExecutor(max_workers=__workerThreads) as pool: threadList = [] removeLogFiles = requestNovelsLib.removeLogFiles() for filePaths in runScritpList: try: threadList.append(pool.submit(lambda p: runTargetScriptsModeAtThread(*p), [filePaths])) except: traceback.print_exc() pool.shutdown(wait=True) for modeResult in threadList: model = modeResult.result() if model is None: continue urlNameFormat = '{0: >20}'.format(f'{model.getRootUrl()}') timeFormat = '{0: <20}'.format(f'{model.getRunTime()}') print(f"====> {urlNameFormat} 执行时间 {timeFormat}") print(f"=================> 所有脚本运行完毕 <=========") else: print("没有找到( 需要运行/可用 )的脚本,请检查参数") else: print("\n====\n\t没有发现运行的脚本\n====\n") ## 是否激活删除选项 getArgs = argvDict.get("rp") if getArgs is not None: print("\n====\n\t移除过期小说信息\n====\n") ## 匹配时间 arrayLen = len(getArgs) day = -1 month = 0 year = 0 if arrayLen > 0: arrayIndex = 0 while arrayIndex < arrayLen: try: if getArgs[arrayIndex] == "day": day = int(getArgs[arrayIndex + 1]) arrayIndex = arrayIndex + 1 elif getArgs[arrayIndex] == "month": month = int(getArgs[arrayIndex + 1]) arrayIndex = arrayIndex + 1 elif getArgs[arrayIndex] == "year": year = int(getArgs[arrayIndex + 1]) arrayIndex = arrayIndex + 1 finally: arrayIndex = arrayIndex + 1 if day == -1: arrayIndex = 0 while arrayIndex < arrayLen: try: day = int(getArgs[arrayIndex]) break finally: arrayIndex = arrayIndex + 1 if day == -1: ## 如果无法找到日期,则使用默认 day = 2 ## 删除过期信息 requestNovelsLib.removeRepeateSqlite3DB(f"{requestNovelsLib.getCallAbsDirPath()}{os.sep}/out/db", day=day, month=month, year=year) else: print("\n====\n\t没有发现 -rp 选项\n====\n") ### 解压和查找选项 writeMakeName = True ## 是否写入文件 userMakeName = True ## 是否读取文件 if argvDict.get("wn") is None: writeMakeName = False if argvDict.get("mn") is None: userMakeName = False ## 是否解压到txt 文件 getArgs = argvDict.get("db") if getArgs is not None: print("\n====\n\t小说信息写入 txt 文件\n====\n") currentPath = requestNovelsLib.getCallAbsDirPath() + os.sep ## 解压文件 dbPath = f"{currentPath}out{os.sep}db{os.sep}" targetPath = f"{currentPath}out{os.sep}txt{os.sep}" requestNovelsLib.getSqlite3DBFileToFiles(dbPath, targetPath, None, writeMakeName, userMakeName) else: print("\n====\n\t没有发现 -db 选项\n====\n") afOption = argvDict.get("af") if afOption is not None and len(afOption) > 0: fOption = argvDict.get("f") if fOption is None: fOption = [] argvDict["f"] = fOption for path in afOption: afOptionFiles = requestNovelsLib.getPathFilesNames(path) for file in afOptionFiles: fOption.append(file) isFind = False kOption = argvDict.get("k") if kOption is not None and len(kOption) < 1: fOption = argvDict.get("f") if fOption is not None and len(fOption) > 0: isFind = True else: isFind = True if not isFind: print("\n====\n\t没有发现需要查找的项目\n====\n") else: print("\n====\n\t开始查找。并且录入 txt 文件\n====\n") ## 获取所有查找的数据库 getRequestFiles = getTargetAbsFilePath("out", "db") workPathRequestFiles = getTargetAbsFilePath(requestNovelsLib.getCallAbsDirPath(), "out/db") for workFileDb in workPathRequestFiles: getRequestFiles.append(workFileDb) workPathRequestFiles.clear() workPathRequestFiles = None if getRequestFiles is None or len(getRequestFiles) == 0: print("\n====\n\t不存在任意数据库,请更新数据库\n====\n") else: keyFindResult = None ## 文件映射到信息 print("获取相关关键小说") ## 文件映射到查找关键字 keyFindMap = initFindKeys(argvDict.get('k'), argvDict.get('f'), argvDict.get('a')) fileContenMap = getFindKeyInfo(keyFindMap, getRequestFiles, currentTimeStr, userMakeName=userMakeName) ## 写入文件 print("\n====\n\t开始写入文件\n====\n") writeFindResultNovels(fileContenMap) exit(0)
小说推荐系统-项目视频:
【爬虫+可视化+协同过滤算法】基于Python的小说推荐系统
计算机毕业设计选题推荐-小说推荐系统-Python项目实战【爬虫+可视化+协同过滤算法】
大家可以帮忙点赞、收藏、关注、评论啦~
源码获取:私信我
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。