搜索引擎的预料库 —— 万恶的爬虫

如何实现高校科技成果快速转化?.docx 如何实现高校科技成果快速转化? 立即下载

640?wx_fmt=png

本节我们来生产一个简单的语料库 —— 从果壳网爬点文章。后面我们将使用这些文章来完成索引构建和关键词查询功能。

https://www.guokr.com/article/438188

果壳网的文章很容易遍历,因为它的文章 id 是自增的。我查阅了站点的最新文章,发现这个 id 还没有超过 45w,所以我打算从 1 开始遍历,扫描出所有的有效文章。

但是扫描 45w 个 URL 会非常漫长,所以我开启了多线程。但是线程也不敢开太多,网站可能有反扒策略快速封禁 IP(我可不想去整 IP 代理池),也可能服务器计算能力有限,爬一爬网站就挂了。

我并不期望自己能扫描出所有的文章,有那么几百篇也就够了,做人也不宜太贪婪。

有同学建议我使用 Go 语言来爬,开启协程比线程方便多了。这个还是留给读者当作学习 Go 语言的练习题吧,我是打算一杆子 Java 写到底了 —— 因为玩 Lucene 是离不开 Java 的。

45w 个文章 ID 如何在多个线程之间分配,需要将所有的 id 塞进一个队列,然后让所有的线程来争抢么?这也是一个办法,不过我选择了使用 AtomicInteger 在多个线程之间共享。

爬到的文章内容放在哪里呢?只放在内存里会丢失,存储到磁盘上有需要序列化和反序列化也梃繁琐,还需要考虑文件内容如何存储。所以我打算把内容统统放到 Redis 中,这会非常方便。但是会不会放不下呢?我们来计算一下,一篇文章的内容量大概会占用 5k,如果有 45w 篇文章,那么就需要 45w * 5k 的内存,大概也只有 2个多G,我的苹果本内存 16G,存这点内容还是绰绰有余的。

爬到的文章是 HTML 格式的,每个网页除了文章内容本身之外,还有很多其它的外链以及广告。那如何将其中的核心文章内容抽取出来,这又是一个问题。我这里选择了 Java 的 HTML 解析库 JSoup,它使用起来有点类似于 JQuery,可以使用选择器来快速定位节点抽取内容。同时它还可以作为一个非常方便的抓取器,自带了 HTTP 的请求工具类。也许读者会以为我会使用高级的机器学习来自动抽取文章内容,很抱歉,实现成本有点高。

下面我们来看看如何使用 JSoup,先导入依赖

<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.12.1</version>
</dependency>

抓取文章,将自己浏览器的 UserAgent 拷贝过来作为机器人的 UserAgent,伪装成一个正常的浏览器。当文章不存在时,果壳网并不是返回标准的 404 错误码。我们需要通过抽取网页内容来判断,如果抽取到的文章标题或者内容是空的,那么我们就认为这篇文章无效不存在。

抽取内容成功后,将内容存储到 Redis 中。因为抽取 45w 个网页时间上会有点漫长,我担心程序可能跑到一半就崩溃了,然后又不得不重新开始遍历。所以我打算记录一下抽取的状态,将抽取成功的文章 id 记录到一个 Redis 集合中。同时因为这 45w 个整数 id 有效的文章有可能连一半都占不到,所以我还会将无效的文章 id 也给记录下来,减少因为程序重启带来的无效爬虫抓取动作。

var agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36";
var url = String.format("https://www.guokr.com/article/%d/", id);
var res = Jsoup.connect(url)
        .header("HOST", "www.guokr.com")
        .header("User-Agent", agent)
        .execute();
if(res.statusCode() == 200) {
    var doc = Jsoup.parse(res.body());
    // 像极了 JQuery 有木有
    var divTitle = "div[class~=layout__Skeleton.*__ArticleTitle.*]";
    var divHTML = "div[class~=layout__Skeleton.*__ArticleContent.*]";
    var title = doc.selectFirst(divTitle).html();
    var html = doc.selectFirst(divHTML).html();
    if(!title.isEmpty() && !html.isEmpty()) {
      save2Redis(id, title, html);
      return;
    }
}
saveFailedId2Redis(id);

将文章内容存储到 Redis 中我打算使用 Hash 结构,分别存储 title 和 html 内容。因为后续我们还需要对文本进行去标签化等操作,这时就可以继续使用 Hash 结构存储处理后的干净的文本内容。

var redis = new JedisPool();
var db = redis.getResource();
// 将有效的文章 id 存储到一个集合中
db.sadd("valid_article_ids", String.valueOf(id));
db.hset(String.format("article_%d", id), "title", title);
db.hset(String.format("article_%d", id), "html", html);
db.close();

代码中的 db.Close() 表示将当前的 Jedis 链接归还给连接池,而不是关闭链接。

无效的文章 id 我们也要存起来。

db = redis.getResource();
db.sadd("invalid_article_ids", String.valueOf(id));
db.close();

这样当每个线程抢到一个 ID 之后,它要做的第一件事就是判断这个 ID 是否在有效的和无效的文章 ID 列表中,如果已经存在了,那就直接去抢下一个文章 ID。

var db = redis.getResource();
if(db.sismember("valid_article_ids", String.valueOf(id))) {
    db.close();
    return;
}
if(db.sismember("invalid_article_ids", String.valueOf(id))) {
    db.close();
    return;
}
db.close();
// 去爬吧
fetchArticle(id);

下面我们再来看看并发线程是如何开启和结束的,我只用了 16 个线程。最后需要使用 thread.join() 来等待所有线程终止,如果没有这行代码,程序会立即退出,想想为什么?

var idGen = new AtomicInteger();
var threads = new Thread[16];
var redis = new JedisPool();
for(int i=0;i<threads.length;i++) {
    threads[i] = new Thread(() -> {
        while(true) {
            var id = idGen.incrementAndGet();
            if(id > 450000) {
                break;
            }
            crawlArticle(redis, id);
        }
    });
    threads[i].start();
}
for(var thread: threads) {
    thread.join();
}
System.out.println("Game Over!");

程序总算跑起来了,但是跑了一段时间后我去 Redis 中查看了一下有效文章 ID 集合,发现里面之后 200 多个有效的文章 ID。果壳网难道只有 200 多篇文章,不可能,果壳网里面的科学文章可是包罗万象,少说应该也有几万篇吧,那这个究竟是怎么回事呢?

于是我将 Redis 中无效的文章 ID 集合清空,又重新跑了一下程序,打印了 HTTP 请求的状态码,发现非常非常多的 503 Service Unavailable 响应。我明白了 —— 网站的反爬策略起作用了,或者是服务扛不住 —— 挂了。我倾向于后者,因为我发现 HTTP 响应时好时坏,服务处于不稳定状态。通常反爬策略会持续一段时间封禁 IP,不会让你一会难受一会爽。

很无奈,我多跑了几次程序,最终收集了不到 1000 篇文章。这作为搜索引擎的语料库也差不多够用了,再死磕下去似乎会很不划算,所以今天的爬虫就到此为止。下一篇文章我们来使用 Lucene 构建文章的索引。

如果你想要仔细阅读今天的爬虫代码,可以点击「阅读原文」进入 Github Gist 查看(有可能需要翻墙)。如果你要尝试本节代码,请将线程数调低一点,以免对果壳网产生 DDOS 攻击 —— 后果自负。

下面是有钱(有老钱)的字节跳动内推入口,找出自己心意的职位后,请勇于投递你的个人简历,内部系统的数据安全性做得非常到位,我是看不到你们的简历内容的,所以不必太担心个人隐私问题。北京、上海、深圳、杭州、成都、广州等城市的职位都有,Python、Java、Golang、算法、数据、分布式计算和存储的岗位也都有,各人发挥自己的搜商自行搜寻。请认真投递自己的简历,否则可能连面试的机会都没有。

640?wx_fmt=png

vue便利购超市存信息管理平台(代码+数据+LW) 摘要 针对便利购超市传统存管理中人工操作效率低、数据同步滞后、权限边界模糊、流程不规范等问题,为实现存管理的数字化、规范化与智能化,提升多角色协同效率,本文设计并实现了一套适配中小型超市实际业务的存信息管理平台。研究以问题为导向,遵循调研分析 - 设计开发 - 测试优化的软件开发流程,先通过文献研究与实地调研梳理核心技术要点与业务需求,明确管理员、管、一线员工三类角色的功能边界;再基于 Vue+Spring Boot+MyBatis 技术栈搭建前后端分离架构,结合 RBAC 角色权限模型与数据第三范式完成系统整体设计,涵盖需求分析、架构设计、功能模块设计、接口与权限控制设计、界面原型设计等环节;随后完成平台前后端开发实现,实现商品及类别管理、存预警、出入与报损管理、全局存管控等九大核心功能,同时针对开发中的权限控制、数据一致性、接口交互等问题提出针对性解决策略;最后通过功能、性能、兼容性多维度测试验证系统有效性。测试结果表明,该平台实现了存管理全流程的线上化,可实现多角色权限的精细化管控、存数据的实时同步与预警信息的即时推送,有效解决了传统存管理的痛点,提升了超市存管理的效率与精准度。系统兼具良好的稳定性、易用性与可扩展性,可为中小型零售超市的存数字化管理提供技术支撑与实践参考,后续可进一步拓展数据分析、智能补货等功能,提升平台的智能化水平。 关键词:存预警;超市;MyBatis 立即下载

相关推荐

故障重构改进深度优先搜索算法配合二进制粒子群的配电网故障恢复重构研究(Matlab代码实现)

内容概要:本文研究了改进深度优先搜索算法与二进制粒子群优化算法相结合在配电网故障恢复重构中的应用,旨在提升故障后网络重构的效率与供电可靠性。通过引入改进的深度优先搜索算法高效生成满足辐射状约束的可行拓扑结构,并结合二进制粒子群算法进行全局优化,实现对开关操作序列的智能决策。文中系统阐述了两种算法的协同机制、适应度函数构建、配电网约束处理(如潮流平衡、电压限值、容量限制)以及孤岛与环网的规避策略,提出了一套完整的故障恢复重构流程。基于Matlab平台的仿真验证表明,该方法能在较短时间内找到高质量的恢复方案,有效恢复失电负荷,避免不合理的网络结构,具有较强的实用性和鲁棒性。; 适合人群:具备电力系统分析基础和Matlab编程能力,从事智能电网、配电自动化、故障诊断与恢复、电力系统优化等方向的科研人员及工程技术人员。; 使用场景及目标:①应对配电网突发故障,快速制定最优网络重构方案以最大化恢复供电范围;②优化故障后开关操作策略,降低停电损失和运行风险;③为配电管理系统(DMS)和自愈控制系统提供高效的算法支撑;④研究启发式算法与图搜索算法在复杂电力网络优化中的融合应用; 阅读建议:建议读者结合Matlab代码深入理解算法实现细节,重点关注深度优先搜索在拓扑可行性校验中的作用以及粒子群算法在离散空间优化中的编码与更新策略,可通过调整网络模型、故障场景和算法参数进行对比实验,以全面掌握其性能特点与适用边界。

统计自然语言处理(第二版)学习笔记:第四章 语料与语言知识

目录: 1.基本概念 2.预料的技术发展 3.国内语料研究状况 4.语料的类型 5.典型语料介绍 1.基本概念 语料(corpus):存放语言材料的仓(语言数据)。 语料语言学(corpus linguistics):基于语料进行语言学研究。 研究内容: 语料的建设与编纂; 语料的加工和管理技术; 语料的使用,包括在语言学研究(言语、 词汇和语义研究等)中的应用和在自然...

XB_please的博客 2732

政府科技管理部门如何优化科技创新服务体系?.docx

科易网基于40亿+科创知识图谱数据,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。

雅思资料汇总

雅思考满分 :听力和单词是预料的单词雅思小站:电子版真题,解析雅思哥:练习口语、查看口语题听力分为 4 个 Section,每个 Section 10 题,难度一般递进。两种题型:填空:基础(单句,问答),表格,图(示意图,流程图,地图)选择配对:多选、单选、配对琐碎生活类对话。例如租房,开账户,报名,看病等,主要目的都是为了让你填写资料,数字,人名地名等。主要就是拼写单词,难度不高,争取全对。文化生活类独白。

银晗的学习博客 4849

【上中课程】词云Word Cloud(标签云、词频分析、文本分析)的实现——应用jieba和wordcloud

词云,又称文字云、标签云,是对文本数据中出现频率较高的“关键词”在视觉上的突出呈现,形成关键词的渲染形成类似云一样的彩色图片,从而一眼就可以领略文本数据的主要表达意思。常见于博客、微博、文章分析等。 基本概念: 1.语 料 预料是我们要分析的所有文档的集合 2.中文分词:指的是将一个汉字序列切成一个一个单独的词 3.停 用 词:数据处理的时候,自动过滤掉某些字或词...

安徐正静 2919

中文语料

https://www.jianshu.com/p/206caa232dedhttps://blog.csdn.net/m0epNwstYk4/article/details/78840688http://www.sogou.com/labs/resource/cs.php

JiaJia 4373

中文语料有哪些

中文自然语言处理开放平台 由中国科学院计算技术研究所·数字化室&软件室创立一个研究自然语言处理的一个平台,里面包含有大量的训练测试语料。 语料:http://www.nlp.org.cn/docs/doclist.php?cat_id=9&type=15 文本语料:http://www.nlp.org.cn/docs/doclist.php?cat_id=16&amp...

飘过的春风 2万+

国内外最好的语料汇总

语料在语言学科研究和深度学习中都至关重要,下面对常用的语料资源进行总结:部分信息来源于其他博客,但是本文会保持持续更新Open Speech and Language Resources http://www.openslr.org/resources.php更新(2020年6月10):若干开源语音数据: https://blog.ailemon.me/2018/11/21/free-open-source-chinese-speech-datasets/更新2020/10/23AISHELL-3 高保

3万+

果壳网科学人文章采集爬虫分享

大数据时代必备技能 - 神箭手云爬虫 -一站式云端通用爬虫开发平台 神箭手云爬虫多样化采集网页内容,快速产生大量而优质的内容。 1.打开神箭手云爬虫官网 2.创建爬虫任务 (1) 在首页点击“爬虫市场”,在神箭手云市场中搜索果壳网; (2)找到果壳网科学人文章采集爬虫,点击“免费获取”; 3.管理爬虫 成功获取果壳网科学人文章采集爬虫

qq_35994328的博客 1027

第一章 获取语料

1.获取文本语料通过import nltk.book 访问定义好的文本通过nltk.corpus.gutenberg.fileids()访问古藤堡项目的文件from nltk.corpus import gutenburg        emma=gutenburg.fileids()       print(emma)  emma=gutenburg.words('austen-emma.txt...

u011588619的博客 2439

搜索引擎-语料

语料通常指为语言研究收集的、用电子形式保存的语言材料,由自然出现的书面语或口语的样本汇集而成,用来代表特定的语言或语言变体。经过科学选材和标注、具有适当规模的语料能够反映和记录语言的实际使用情况。人们通过语料观察和把握语言事实,分析和研究语言系统的规律。语料已经成为语言学理论研究、应用研究和语言工程不可缺少的基础资源。语料有多种类型,确定类型的主要依据是它的研究目的和用途,这一点往往能够

John.Deng的专栏 2050

针对搜索引擎爬虫的欺骗式SSR

玩Google Webmasters的可能会有这种经历。自己开发的app用了Vue/React,写完后用Fetch as Google一爬傻眼了,爬不到东西。 网上搜解决方案出来的都是一堆额外的SSR框架,要上node,还看起来麻烦的要死。对于已经完成的项目,为了让搜索引擎爬虫能爬几个页面,又是改前端代码,又是改后端语言真的是郁闷。 一种...

weixin_34383618的博客 951

一个朴素的搜索引擎实现

今天我们要使用 Lucene 来实现一个简单的搜索引擎,我们要使用上一节爬取的果壳网语料来构建索引,然后在索引的基础上进行关键词查询。上一节果壳网的语料放在了 Red...

codehole_的博客 751

情感分析语料资源(免费)

1.知网的情感词典-http://www.keenage.com/html/c_bulletin_2007.htm由知网发布的词典,包括中文情感词典和英文情感词典 2.台湾大学的情感极性词典-http://www.datatang.com/data/11837包括2810个正极性词语和8276个负极性词语准确度很高 3.酒店评论语料-http://www.datatang.c...

weixin_30853329的博客 2516

SSR(服务器渲染)和BSR(客户端渲染)及 SEO(搜索引擎优化)

SSR:服务端渲染 M+V发生在服务器端, 对营销推广要求较高的产品,会使用SSR,比如企业官网 1) 服务器的压力更大 2) 页面访问和显示速度更快(DOM少) 3) 有利于SEO搜索引擎优化(有利于公司品牌和业务的推广) 4) 前端不分离,对后端工程师要求更高,工作量更大 5) 功能比较简单的产品,交互简单的产品 BSR:客户端渲染 M+V发生在客户端 对营销推广要求不高的产品,使用BSR,比如管理系统 1)客户端压力较大 2)页面加载速度更慢(DOM多) 3)不利于SEO优化 4)前后端分离,便于

qq_44951057的博客 876

搜索引擎白给你shell

经典的用户名密码'or'='or''or'1'='1网上好多这样的文章我的只不过是来个小总结,恩其实光是总结还不够,因为我写的还不是很全面。其实搜索这些漏洞我们必须要先连接关于搜索引擎的一些语法下面给大家介绍一下inurl: 用于搜索网页上包含的URL. 这个语法对寻找网页上的搜索,帮助之类的很有用. intext: 只搜索网页<body>部分中包含的文字(也就是...

weixin_33726318的博客 620

政府科技管理部门如何提升科技成果转化效率?.docx

科易网基于40亿+科创知识图谱数据,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。

上一篇: 字节跳动面试题 —— 史莱姆变形计
下一篇: 5折抢购最后一天 | 戴尔顶级配置电脑,限时秒!
codehole_
博客等级 码龄7年 33粉丝 132原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值