[955]readability网页内容提取器

2023-10-08 17:50

本文主要是介绍[955]readability网页内容提取器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 相关阅读1
    • 相关阅读2
    • 相关阅读3

相关阅读1

github:https://github.com/buriy/python-readability/

pip install readability-lxml

使用1

>>> import requests
>>> from readability import Document>>> response = requests.get('http://example.com')
>>> doc = Document(response.text)
>>> doc.title()
'Example Domain'>>> doc.summary()
"""<html><body><div><body id="readabilityBody">\n<div>\n    <h1>Example Domain</h1>\n
<p>This domain is established to be used for illustrative examples in documents. You may
use this\n    domain in examples without prior coordination or asking for permission.</p>
\n    <p><a href="http://www.iana.org/domains/example">More information...</a></p>\n</div>
\n</body>\n</div></body></html>"""

使用2

# encoding:utf-8
import html2text
import requests
import re
from readability.readability import Documentres = requests.get('http://finance.sina.com.cn/roll/2019-02-12/doc-ihrfqzka5034116.shtml')# 获取新闻标题
readable_title = Document(res.content).short_title()
# 获取内容并清洗
readable_article = Document(res.content).summary()
text_p = re.sub(r'</?div.*?>', '', readable_article)
text_p = re.sub(r'((</p>)?<a href=.*?>|</a>(<p>)?)', '', text_p)
text_p = re.sub(r'<select>.*?</select>', '', text_p)
print(text_p)

html2text的使用:

pip install html2text
ef test_func2(html):
"""获取指定URL的html,对html进行处理"""h = html2text.HTML2Text()h.ignore_links = True  # (True剔除超链接,False保留)print(h.handle(html))
res = requests.get('http://finance.sina.com.cn/roll/2019-02-12/doc-ihrfqzka5034116.shtml')test_func2(res.content.decode('utf-8'))

相关阅读2

官网:https://www.readability.com/

提取内容的api文档:https://www.readability.com/developers/api/parser

注册一下,在个人页面可以找到你自己的token

API - GET请求,带上token和url参数:
https://www.readability.com/api/content/v1/parser?token=your_token&url=url_you_want_to_parse

响应示例—json格式返回数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lF8jeTZj-1618145745065)(//upload-images.jianshu.io/upload_images/901735-34f5ca7d416b096c.png?imageMogr2/auto-orient/strip|imageView2/2/w/1200/format/webp)]

来看个中文的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jpyt6GZv-1618145745069)(//upload-images.jianshu.io/upload_images/901735-93ac59da35118ccb.png?imageMogr2/auto-orient/strip|imageView2/2/w/1200/format/webp)]

content部分就是提取的网页内容了,将其写入html文件,可以直接打开显示网页内容
如果你只是为了提取和保存内容,到这里就可以了。

如果你需要得到网页内容,并进行一些处理,那可能就得把&#x开头的内容转换成中文了&#x开头的是什么编码?,可能需要进行以下操作

# 去掉content中的html标记
def remove_html_tag(content):return re.sub(r'</?\w+[^>]*>', '', content)
# 转换成中文
def convert_to_cn(text):# 需要将 × 这种先做补全,×text = re.sub(r'&#x([A-F0-9]{2});', r'&#x00\1;', text)return text.replace('&#x', '\u').replace(';', '') \.decode('unicode-escape').encode('utf-8')

相关阅读3

从网页中提取出主要内容,一直是一个比较有挑战的算法。Readability是其中一个很不错的实现,它通过遍历Dom对象,通过标签和常用文字的加减权,来重新整合出页面的内容。

JS版本的Readability是最好用的,它可以直接在浏览器完成分析,于是用户还可以人工对分析出来的内容进行修改和校正。

GET社区的Chrome插件就使用了这个算法,在你遇到读起来不爽的网页的时候,点一下,世界就清爽了。

比如Breach浏览器的文档页面,看起来很酷,但是阅读久了会让人泪流不止。

image.png

但当你点过插件后,这个页面会变成这个样子:

image.png

是不是觉得世界更美好了。

那么,接下来我们就简单看看这个算法是如何实现的。

首先,它定义了一系列正则:

regexps: {unlikelyCandidates:    /combx|comment|community|disqus|extra|foot|header|menu|remark|rss|shoutbox|sidebar|sponsor|ad-break|agegate|pagination|pager|popup|tweet|twitter/i,okMaybeItsACandidate:  /and|article|body|column|main|shadow/i,positive:              /article|body|content|entry|hentry|main|page|pagination|post|text|blog|story/i,negative:              /combx|comment|com-|contact|foot|footer|footnote|masthead|media|meta|outbrain|promo|related|scroll|shoutbox|sidebar|sponsor|shopping|tags|tool|widget/i,extraneous:            /print|archive|comment|discuss|e[\-]?mail|share|reply|all|login|sign|single/i,divToPElements:        /<(a|blockquote|dl|div|img|ol|p|pre|table|ul)/i,replaceBrs:            /(<br[^>]*>[ \n\r\t]*){2,}/gi,replaceFonts:          /<(\/?)font[^>]*>/gi,trim:                  /^\s+|\s+$/g,normalize:             /\s{2,}/g,killBreaks:            /(<br\s*\/?>(\s|&nbsp;?)*){1,}/g,videos:                /http:\/\/(www\.)?(youtube|vimeo)\.com/i,skipFootnoteLink:      /^\s*(\[?[a-z0-9]{1,2}\]?|^|edit|citation needed)\s*$/i,nextLink:              /(next|weiter|continue|>([^\|]|$)|»([^\|]|$))/i, // Match: next, continue, >, >>, » but not >|, »| as those usually mean last.prevLink:              /(prev|earl|old|new|<|«)/i},

可以看到,标签和文字都有加权或降权分组。整个内容分析是通过grabArticle函数来实现的。

首先开始遍历节点

for(var nodeIndex = 0; (node = allElements[nodeIndex]); nodeIndex+=1) 

然后将不像内容的元素去掉

if (stripUnlikelyCandidates) 
{var unlikelyMatchString = node.className + node.id;if ((unlikelyMatchString.search(readability.regexps.unlikelyCandidates) !== -1 &&unlikelyMatchString.search(readability.regexps.okMaybeItsACandidate) === -1 &&node.tagName !== "BODY")){dbg("Removing unlikely candidate - " + unlikelyMatchString);node.parentNode.removeChild(node);nodeIndex-=1;continue;}               
}

将DIV替换为P标签后,再对目标节点进行遍历,进行计分:

var candidates = [];
for (var pt=0; pt < nodesToScore.length; pt+=1) {var parentNode      = nodesToScore[pt].parentNode;var grandParentNode = parentNode ? parentNode.parentNode : null;var innerText       = readability.getInnerText(nodesToScore[pt]);if(!parentNode || typeof(parentNode.tagName) === 'undefined') {continue;}/* If this paragraph is less than 25 characters, don't even count it. */if(innerText.length < 25) {continue; }/* Initialize readability data for the parent. */if(typeof parentNode.readability === 'undefined') {readability.initializeNode(parentNode);candidates.push(parentNode);}/* Initialize readability data for the grandparent. */if(grandParentNode && typeof(grandParentNode.readability) === 'undefined' && typeof(grandParentNode.tagName) !== 'undefined') {readability.initializeNode(grandParentNode);candidates.push(grandParentNode);}var contentScore = 0;/* Add a point for the paragraph itself as a base. */contentScore+=1;/* Add points for any commas within this paragraph */contentScore += innerText.split(',').length;/* For every 100 characters in this paragraph, add another point. Up to 3 points. */contentScore += Math.min(Math.floor(innerText.length / 100), 3);/* Add the score to the parent. The grandparent gets half. */parentNode.readability.contentScore += contentScore;if(grandParentNode) {grandParentNode.readability.contentScore += contentScore/2;             }
}

最后根据分值,重新拼接内容

var articleContent        = document.createElement("DIV");
if (isPaging) {articleContent.id     = "readability-content";
}
var siblingScoreThreshold = Math.max(10, topCandidate.readability.contentScore * 0.2);
var siblingNodes          = topCandidate.parentNode.childNodes;for(var s=0, sl=siblingNodes.length; s < sl; s+=1) {var siblingNode = siblingNodes[s];var append      = false;/*** Fix for odd IE7 Crash where siblingNode does not exist even though this should be a live nodeList.* Example of error visible here: http://www.esquire.com/features/honesty0707**/if(!siblingNode) {continue;}dbg("Looking at sibling node: " + siblingNode + " (" + siblingNode.className + ":" + siblingNode.id + ")" + ((typeof siblingNode.readability !== 'undefined') ? (" with score " + siblingNode.readability.contentScore) : ''));dbg("Sibling has score " + (siblingNode.readability ? siblingNode.readability.contentScore : 'Unknown'));if(siblingNode === topCandidate){append = true;}var contentBonus = 0;/* Give a bonus if sibling nodes and top candidates have the example same classname */if(siblingNode.className === topCandidate.className && topCandidate.className !== "") {contentBonus += topCandidate.readability.contentScore * 0.2;}if(typeof siblingNode.readability !== 'undefined' && (siblingNode.readability.contentScore+contentBonus) >= siblingScoreThreshold){append = true;}if(siblingNode.nodeName === "P") {var linkDensity = readability.getLinkDensity(siblingNode);var nodeContent = readability.getInnerText(siblingNode);var nodeLength  = nodeContent.length;if(nodeLength > 80 && linkDensity < 0.25){append = true;}else if(nodeLength < 80 && linkDensity === 0 && nodeContent.search(/\.( |$)/) !== -1){append = true;}}if(append) {dbg("Appending node: " + siblingNode);var nodeToAppend = null;if(siblingNode.nodeName !== "DIV" && siblingNode.nodeName !== "P") {/* We have a node that isn't a common block level element, like a form or td tag. Turn it into a div so it doesn't get filtered out later by accident. */dbg("Altering siblingNode of " + siblingNode.nodeName + ' to div.');nodeToAppend = document.createElement("DIV");try {nodeToAppend.id = siblingNode.id;nodeToAppend.innerHTML = siblingNode.innerHTML;}catch(er) {dbg("Could not alter siblingNode to div, probably an IE restriction, reverting back to original.");nodeToAppend = siblingNode;s-=1;sl-=1;}} else {nodeToAppend = siblingNode;s-=1;sl-=1;}/* To ensure a node does not interfere with readability styles, remove its classnames */nodeToAppend.className = "";/* Append sibling and subtract from our list because it removes the node when you append to another node */articleContent.appendChild(nodeToAppend);}
}

可以看到,里边用到了很多很trick的技巧,比如25字以下的段落不计分。

整个读下来,还是很有趣的。

由于Readability解决的需求很通用,于是其他语言的程序员纷纷移植了该算法。

  1. PHP版本:https://github.com/feelinglucky/php-readability
  2. Java版本:https://github.com/wuman/JReadability
  3. 当然会有Node版本了:https://www.npmjs.org/package/node-readability

参考:https://www.jianshu.com/p/b9cbb843e807
https://blog.csdn.net/qq_40659982/article/details/88071546
http://get.ftqq.com/130.get

这篇关于[955]readability网页内容提取器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/166983

相关文章

ROS - C++实现RosBag包回放/提取

文章目录 1. 回放原理2. 回放/提取 多个话题3. 回放/提取数据包,并实时发布 1. 回放原理 #include <ros/ros.h>#include <rosbag/bag.h>#include <std_msgs/String.h>int main(int argc, char** argv){// 初始化ROS节点ros::init(argc, argv,

HalconDotNet中的图像特征与提取详解

文章目录 简介一、边缘特征提取二、角点特征提取三、区域特征提取四、纹理特征提取五、形状特征提取 简介   图像特征提取是图像处理中的一个重要步骤,用于从图像中提取有意义的特征,以便进行进一步的分析和处理。HalconDotNet提供了多种图像特征提取方法,每种方法都有其特定的应用场景和优缺点。 一、边缘特征提取   边缘特征提取是图像处理中最基本的特征提取方法之一,通过检

如何根据相同分隔符提取间隔数据?

最近遇到很多提问怎么提取字符的,而这些问题都有一个相同的特征,就是要提取的内容与内容之间,都有着相同的分隔符。当然,这种问题直接用“数据” →  “分列”功能就可以一步到位实现的,但有人喜欢折腾,而更多的人又非得指定函数公式的方法,或者更多的是要保持数据的同步性。   下面,我们就来讲讲用函数公式应该怎么实现这个提取,首先来个数据和要求,如下图,将 - 号间隔的内容依次提取到右边单元格内:

Java8特性:分组、提取字段、去重、过滤、差集、交集

总结下自己使用过的特性 将对象集合根据某个字段分组 //根据id分组Map<String, List<Bean>> newMap = successCf.stream().collect(Collectors.groupingBy(b -> b.getId().trim())); 获取对象集合里面的某个字段的集合 List<Bean> list = new ArrayList<>

0基础学习爬虫系列:网页内容爬取

1.背景 今天我们来实现,监控网站最新数据爬虫。 在信息爆炸的年代,能够有一个爬虫帮你,将你感兴趣的最新消息推送给你,能够帮你节约非常多时间,同时确保不会miss重要信息。 爬虫应用场景: 应用场景主要功能数据来源示例使用目的搜索引擎优化 (SEO)分析关键词密度、外部链接质量等网站元数据、链接提升网站在搜索引擎中的排名市场研究收集竞品信息、价格比较电商网站、行业报告制定更有效的市场策略舆情

OpenCV结构分析与形状描述符(10)检测并提取轮廓函数findContours()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C++11 算法描述 在二值图像中查找轮廓。 该函数使用算法 253从二值图像中检索轮廓。轮廓是有用的工具,可用于形状分析和对象检测与识别。参见 OpenCV 示例目录中的 squares.cpp。 findContours 是 OpenCV 库中的一个重要函数

【python 走进pytotch】pytorch实现用Resnet提取特征

无意中发现了一个巨牛的人工智能教程,忍不住分享一下给大家。教程不仅是零基础,通俗易懂, 而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家。点这里可以跳转到教程。人工智能教程 准备一张图片,pytorch可以方便地实现用预训练的网络提取特征。 下面我们用pytorch提取图片采用预训练网络resnet50,提取图片特征。 # -*- coding: utf-8 -*-import os

mhtml图片提取 百度图片下载

如果你需要找一些图片,可以先去百度一下,待相关网页加载完成后,点击保存,即可得到一个mhtml文件。这个文件里的图片会用base64进行存储,只需要找到他们并转化就可以。目前在美篇之类的网站上效果还一般,需要继续排查问题。 效果 代码 大概分为提取所有base64、转化为图片两步。 import base64from io import BytesIOfrom PIL import

python转换并提取pdf文件中的图片

#安装fitz包pip install pymupdf 脚本如下所示: import fitzimport reimport osimport timeimport sysarguments = sys.argvfor arg in arguments:print(arg)def file_name_list(base_dir):for i, j, k in os.walk(b

如何提取JKS文件的证书和私钥?

文章来源 https://jingyan.baidu.com/article/066074d61de50cc3c21cb0ba.html 验证命令如下: > 生成证书文件:keytool -genkey -alias server_cert -keypass 12345678 -keyalg RSA -keysize 1024 -validity 365-keystore