基于Python实现的文章整合搜索引擎网站(Scrapy+Django+MySQL)

news/2024/5/2 4:20:16/文章来源:https://blog.csdn.net/newlw/article/details/127683116

目 录
摘 要… 1
1 概述… 6
2 技术选型… 6
2.1 Scrapy-Redis 分布式爬虫 … 6
2.1.1 Redis… 6
2.1.2 Scrapy… 7
2.2 MySQL 数据存储 … 8
2.3 Django 搭建搜索网站 … 8
2.4 ElasticSearch 搜索引擎 … 9
2.4.1 Elasticsearch-RTF… 9
2.4.2 Elasticsearch-head… 10
2.4.3 Kibana… 10
3 实现细节… 10
3.1 处理反爬… 10
3.1.1 更换随机 User-Agent … 10
3.1.2 使用 IP 代理池… 11
3.1.3 访问频率限制… 12
3.1.4 Cookie 的禁用 … 13
3.1.5 验证码识别… 13
3.2 爬取数据… 14
3.2.1 先知社区… 14
3.2.2 安全客… 17
3.2.3 嘶吼… 19
3.3 重构分布式爬虫… 21
3.3.1 需要解决的问题… 21
3.3.2 分布式的原理… 22
3.3.3 分布式的实现… 23
3.4 搜索引擎… 24
3.4.1 倒排索引… 24
3.4.2 排序评分… 25
3.4.3 搜索提示… 26
3.4.4 模糊搜索… 27
3.5 网页搭建… 28
3.5.1 爬虫统计数据… 28
3.5.2 热门搜索… 28
3.6 其他技术… 29
3.6.1 URL 去重策略 … 29
3.6.2 Bloom Filter 使用 … 31
4 系统展示 … 34
4.1 分布式爬取… 34
4.2 搜索网站首页… 36
4.3 搜索提示展示… 36
4.4 搜索结果展示… 37
1概述
爬虫的应用领域非常广泛,目前利用爬虫技术市面上已经存在了比较成熟的搜索引擎产品,如百度、谷歌,以及其他垂直领域搜索引擎,这些都是非直接目的;还有一些推荐引擎,如今日头条,可以定向给用户推荐相关新闻;爬虫还可以用来作为机器学习的数据样本。
本项目的主要目的是为了更好的整合利用安全领域特有的社区资源优势。首先使用 Scrapy 爬虫框架结合 NoSQL 数据库 Redis 编写分布式爬虫,并对先知、安全客、嘶吼三个知名安全社区进行技术文章的爬取;然后选取 ElasticSearch 搭建搜索服务,同时提供了 RESTfulweb 接口;最后通过 Django 搭建可视化站点,供用户透明的对文章进行搜索。
最终通过本项目可以更加透彻的理解爬虫的相关知识;在熟练运用 Python 语言的基础上,更加深入的掌握开源的爬虫框架 Scrapy,为后续其他与爬虫相关的业务奠定理论基础和数据基础;进一步理解分布式的概念,为大数据的相关研究和硬件条件奠定基础;熟练掌握 Python 搭建网站的框架 Django,深入理解基于 Lucene 的搜索服务器 ElasticSearch。
2技术选型
2.1Scrapy-Redis 分布式爬虫
2.1.1Redis
Redis 是完全开源免费的,遵守 BSD 协议的,高性能的 key-value 数据库。
Redis 与其他 key-value 缓存产品有以下三个特点:
(1)Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。这样可以防止数据的丢失,在实际生产应用中数据的完整性是必须保证的。
(2)Redis 不仅仅支持简单的 key-value 类型的数据,同时还提供 list,set,
zset,hash 等数据结构的存储。这些功能更强大的数据存储方式极大地节约了存储空间,优化了查询的性能,大大提高了查询效率。存储的目的是为了后期更好的取出,Redis 很好地做到了这一点。
(3)Redis 支持数据的备份,即 master-slave 模式的数据备份。主从结构目前是大数据里面的主流结构,主从模式能保证数据的健壮性和高可用。当出现电脑宕机,硬盘损坏等重大自然原因时,本文转载自http://www.biyezuopin.vip/onews.asp?id=16995主从模式能很好的保证存储的数据不丢失, 随时恢复到可用状态。
2.1.2Scrapy
Scrapy 的原理如下所示:
在这里插入图片描述

<!DOCTYPE html >
<html xmlns="http://www.w3.org/1999/xhtml">
{% load staticfiles %}
<head><meta http-equiv="X-UA-Compatible" content="IE=emulateIE7"/><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><title>ISA Search 搜索引擎</title><link href="{% static 'css/style.css' %}" rel="stylesheet" type="text/css"/><link href="{% static 'css/index.css' %}" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="container"><div id="bd"><div id="main"><h1 class="title"><div class="logo large"></div></h1><div class="inputArea"><input type="text" class="searchInput"/><input type="button" class="searchButton" onclick="add_search()"/><ul class="dataList"></ul></div><div class="historyArea"><p class="history"><label>热门搜索:</label>{% for search_word in topn_search %}<a href="/search?q={{ search_word }}">{{ search_word }}</a>{% endfor %}</p><p class="history mysearch"><label>我的搜索:</label><span class="all-search"><a href="javascript:;"></a></span></p></div></div><!-- End of main --></div><!--End of bd--></div>
</body>
<script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
<script type="text/javascript" src="{% static 'js/global.js' %}"></script>
<script type="text/javascript">var suggest_url = "{% url 'suggest' %}"var search_url = "{% url 'search' %}"$('.searchList').on('click', '.searchItem', function () {$('.searchList .searchItem').removeClass('current');$(this).addClass('current');});function removeByValue(arr, val) {for (var i = 0; i < arr.length; i++) {if (arr[i] == val) {arr.splice(i, 1);break;}}}// 搜索建议$(function () {$('.searchInput').bind(' input propertychange ', function () {var searchText = $(this).val();var tmpHtml = ""$.ajax({cache: false,type: 'get',dataType: 'json',url: suggest_url + "?s=" + searchText,async: true,success: function (data) {for (var i = 0; i < data.length; i++) {tmpHtml += '<li><a href="' + search_url + '?q=' + data[i] + '">' + data[i] + '</a></li>'}$(".dataList").html("")$(".dataList").append(tmpHtml);if (data.length == 0) {$('.dataList').hide()} else {$('.dataList').show()}}});});})hideElement($('.dataList'), $('.searchInput'));</script>
<script>function htmlSpecialChars(str) {var s = "";if (str.length == 0) return "";for (var i = 0; i < str.length; i++) {switch (str.substr(i, 1)) {case "<":s += "&lt;";break;case ">":s += "&gt;";break;case "&":s += "&amp;";break;case " ":if (str.substr(i + 1, 1) == " ") {s += " &nbsp;";i++;} else s += " ";break;case "\"":s += "&quot;";break;case "\n":s += "<br>";break;default:s += str.substr(i, 1);break;}}return s;}var searchArr;//定义一个search的,判断浏览器有无数据存储(搜索历史)if (localStorage.search) {//如果有,转换成 数组的形式存放到searchArr的数组里(localStorage以字符串的形式存储,所以要把它转换成数组的形式)searchArr = localStorage.search.split(",")} else {//如果没有,则定义searchArr为一个空的数组searchArr = [];}//把存储的数据显示出来作为搜索历史MapSearchArr();function add_search() {var val = $(".searchInput").val();if (val.length >= 2) {//点击搜索按钮时,去重KillRepeat(val);//去重后把数组存储到浏览器localStoragelocalStorage.search = searchArr;//然后再把搜索内容显示出来MapSearchArr();}window.location.href = search_url + '?q=' + val}function MapSearchArr() {var tmpHtml = "";var arrLen = 0if (searchArr.length >= 5) {arrLen = 5} else {arrLen = searchArr.length}for (var i = 0; i < arrLen; i++) {tmpHtml += '<a href="' + search_url + '?q=' + searchArr[i] + '">' + htmlSpecialChars(searchArr[i]) + '</a>'}$(".mysearch .all-search").html(tmpHtml);}//去重function KillRepeat(val) {var kill = 0;for (var i = 0; i < searchArr.length; i++) {if (val === searchArr[i]) {kill++;}}if (kill < 1) {searchArr.unshift(val);} else {removeByValue(searchArr, val)searchArr.unshift(val)}}</script>
</html>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_412017.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kotlin编程实战——集合(07)

一 概述 集合概述构造集合迭代器(Iterable<T>)区间与数列序列(Sequence<T>)集合操作概述集合转换集合过滤加减操作符分组(groupBy())取集合的一部分取单个元素集合排序集合聚合操作集合写操作List 相关操作Set 相关操作Map 相关操作 二 集合概述 set、list 、map…

【python】Numpy统计函数总结

文章目录函数列表相关系数直方图函数列表 最值amin, amax, nanmin, nanmax, 极差ptp分位数percentile∗^*∗ quantile∗^*∗,统计量中位数median∗^*∗&#xff1b;平均数mean∗^*∗&#xff1b;变化幅度var&#xff1b;加权平均average标准差std&#xff1b;协方差cov&#x…

运算放大器正反馈负反馈判别法

---------------------------------------------------------------------------------------------------------------- 反馈可分为负反馈和正反馈。前者使输出起到与输入相反的作用&#xff0c;使系统输出与系统目标的误差减小&#xff0c;系统趋于稳定&#xff1b;后者使输出…

浅谈java中的String

Java中的String类型不属于八大基本数据类型&#xff0c;而是一个引用数据类型&#xff0c;所以在定义一个String对象的时候如果不直接赋值给这个对象&#xff0c;它的默认值就是null。我们要怎么理解String类型的不可变&#xff0c;在JDK源码中String这个类的value方法被final关…

【C++】如何修改set的值

问题&#xff1a;尝试通过begin方法得到的迭代器去修改值&#xff0c;发现会报错。 set<string> st{"hello", "world", "good"}; set<string>::iterator it st.begin(); *it "test"; 原因&#xff1a;我们可以在源码里…

怎么搭建搜题接口api

怎么搭建搜题接口api 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&#xff08;点击…

RTSP协议学习Ubuntu环境准备

文章目录RTSP协议学习Ubuntu环境准备RTSP协议概述Ubuntu环境准备一、Ubuntu安装FFmpeg二、安装ZLMediaKit1、获取代码2、强烈推荐3、编译器3.1、编译器版本要求3.2、安装编译器4、cmake5、依赖库5.1、依赖库列表5.2、安装依赖库6、构建和编译项目7、运行8、测试三、测试推流测试…

【Tomcat】解决Tomcat服务器乱码问题

俩地方开展出现乱码的原因1、以startup.bat文件打开的服务器出现乱码2、在IDEA中运行Tomcat服务器出现乱码问题3、有关社区版IDEA如何开发JavaWeb项目出现乱码的原因 使用了错误的字符编码去解码字节流&#xff0c;所以出现乱码咱思维要清晰&#xff0c;就去找字符编码是否与其…

【TS04——接口的多态——泛型接口】

接口的多态&#xff0c;同一个方法&#xff0c;传入不同的参数&#xff0c;他所对应的操作不同成为多态【参数不同】或者可以理解为同一个方法&#xff0c;返回不同的结果&#xff0c;称之多态。 interface IfnPerson {run():voidrun(id:number):voidrun(id:number,name:strin…

【生日快乐】Node.js 实战 第1章 欢迎进入Node.js 的世界 1.3 安装Node

Node.js 实战 文章目录Node.js 实战第1章 欢迎进入Node.js 的世界1.3 安装Node第1章 欢迎进入Node.js 的世界 1.3 安装Node 安装Node的最简单的方法是使用其官网上的安装程序。可以用对应Mac或 Windows的安装程序安装最新的当前版。 官网安装包下载地址&#xff1a;https://…

Jenkins部署详细教程

Jenkins简介 Jenkins 是一个可扩展的持续集成引擎。是一个自成一体的开源自动化服务器, 可用于自动化与构建、测试、交付或部署软件相关的各种任务; Jenkins是一个高度可扩展的产品, 其功能可以通过安装插件来扩展。 在gitlab里可以完成源代码的管理&#xff0c;但是对于研发…

[ACTF2020 新生赛]Exec1命令注入

1.来看题目如下 得到一个ping的输入框&#xff0c;老样子先检查网页源码看有没有什么好东西&#xff0c;得到一个链接&#xff0c;我们来访问一下 发现也没什么有用处的信息&#xff0c;于是看到题目的标题之后联想到了命令注入&#xff0c; 那么是怎么判断使用命令注入的呢&am…

MyBatis初步了解

1.Mybatis简介 1.1原始jdbc操作&#xff08;查询数据&#xff09; 1.2原始jdbc操作&#xff08;插入数据&#xff09; 1.3 原始jdbc操作的分析 原始jdbc开发存在的问题如下&#xff1a; ①数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能 ②sql 语句在代码中硬编…

深入理解Java虚拟机:Java运行内存结构

本篇内容包括&#xff1a;JAVA 运行内存结构&#xff0c;即 程序计数器、Java 虚拟机栈、本地方法栈 、Java堆、方法区、运行时常量池 以及 直接内存等相关内容&#xff01; 一、JAVA 运行内存结构 Jvm 执行 Java 程序时&#xff0c;会把它所管理的内存划分为若干个不同的数据…

软件设计与体系——创建型模式

如果有兴趣了解更多相关内容&#xff0c;欢迎来我的个人网站看看&#xff1a;瞳孔的个人空间 创建型模式&#xff1a; 创建型模式抽象了实例化过程帮助系统独立于如何创建、组合和表示对象 一个类创建型模式使用继承改变被实例化的类类创建型模式使用继承改变被实例化的类对象…

自学Python需要掌握哪些知识点?怎么学?

其实这个问题你可以转换一下思路&#xff0c;自学python有什么合适的学习路线&#xff0c;基本路线里涉及到的都是需要掌握的~ 单个知识点那罗列起来可是太多了~ 另外你可以考虑下你自学python的目的和方向&#xff0c;是单纯兴趣还是说要学了就业~ 想往人工智能方向发展还是P…

如何实现CAN/LIN通信路由测试?

目前车载网络通信越来越复杂&#xff0c;通信总线、协议多种多样&#xff0c;网关作为信息交互的载体&#xff0c;主要通过报文路由转发、报文过滤、信号重组等方式实现不同网段、不同协议间的信息交互&#xff1b;在复杂的车载网络中&#xff0c;网关通信路由转发功能具有非常…

软件设计师--数据结构考点细节总结

视频2022软件设计师-提炼高频考点-个人学习过程的总结&#xff0c;仅供参考&#xff01;_哔哩哔哩_bilibili 目录 1&#xff0c;栈 2,二叉树 3&#xff0c;HUFFMAN 特点&#xff1a; 4&#xff0c;文件压缩比 5&#xff0c;拓扑排序 -- 有向无环图 6&#xff0c;查找 7…

CSDN编程竞赛第八期 | 参赛经历分享

参赛经历分享 一共参与七次了&#xff0c;这是我第二次在CSDN竞赛上获奖&#xff0c;上一次获奖是在第四期&#xff0c;获得了第三名&#xff0c;拿到了一个高级背包、一件T恤和一个获奖证书&#xff0c;我之前拍照发过动态的&#xff0c;详情请见&#xff1a;动态 - CSDN 然后…

机器视觉(三):摄像机标定技术

目录&#xff1a; 机器视觉&#xff08;二&#xff09;&#xff1a;机器视觉硬件技术 机器视觉&#xff08;三&#xff09;&#xff1a;摄像机标定技术 &#x1f30f;&#x1f9d0;以下为正文&#x1f984;&#x1fa90; 摄像机标定的目的&#xff1a;三维重建 空间物体表面…