文章采集程序(2019年10月28日更新:录制了一个YouTube视频)
优采云 发布时间: 2022-04-02 19:19文章采集程序(2019年10月28日更新:录制了一个YouTube视频)
2019 年 10 月 28 日更新:
录制了一段YouTube视频,详细解释了步骤:
youtu.be/T-hVHJO0ya0
================================================
从2014年开始我就一直在做批量的内容采集,最初的目的是做一个html5垃圾邮件网站。当时垃圾站采集的内容很容易在里面传播。那个时候批量采集很容易做,采集入口就是历史新闻页面。这个条目到今天还是一样,只是越来越难了采集。采集 的方法也更新了很多版本。后来在2015年,html5垃圾站不再做,转而在本地新闻资讯类中定位采集,前端展示做成app。于是一个可以自动采集内容的新闻app就形成了。我曾经担心技术升级后的一天就无法采集内容了,我的新闻应用程序会失败。但随着技术的不断升级,采集的方法也不断升级,让我越来越自信。只要历史新闻页面存在,就可以批量采集到内容。所以今天决定整理一下采集方法,写下来。我的方法来源于很多同事的分享精神,所以我会延续这种精神,分享我的成果。
本文文章会持续更新,保证您看到的内容在您看到的时候可用。
首先我们来看一个历史新闻页面的链接地址:
?__biz=MjM5MzczNjY2NA==#wechat_webview_type=1&wechat_redirect
=========2017 年 1 月 11 日更新==========
现在,根据不同的个人号码,会有两个不同的历史消息页地址。以下是另一个历史消息页面的地址。第一个地址的链接在anyproxy中会显示302跳转:
?action=home&__biz=MzA3NDk5MjYzNg==&scene=124#wechat_redirect
第一个链接地址的页面样式:
第二个链接地址的页面样式:
根据目前掌握的资料,两种页面形式不规则地以不同的编号出现,有的编号始终是第一页格式,有的始终是第二页格式。
上面的链接是历史新闻页面的真实链接,但是如果我们在浏览器中输入这个链接,会显示:请从客户端访问。这是因为链接地址实际上需要几个参数才能正常显示内容。我们来看看一个可以正常显示内容的完整链接是什么样子的:
//第一个链接//第二个 %2BeHsAqhbjJCwzTfV48u%2FCZRRGTmI8oqmHDxxfEL8ke%2B&_header=1
该地址是在客户端打开历史消息页面后,通过后面介绍的代理服务器软件获得的。这里有几个参数:
action=;__biz=;uin=;key=;devicetype=;version=;lang=;nettype=;scene=;pass_ticket=;_header=;
重要的参数是:__biz;uin=;key=;pass_ticket=; 这四个参数。
__biz是一个类似于id的参数,每个都有一个biz,目前这个biz会以极小概率发生变化的事件;
其余三个参数与用户的id和token相关,这三个参数的值在客户端生成后自动添加到地址栏。所以我们想通过客户端应用程序采集。在以前的版本中,这三个参数也可以在有效期内获取一次,然后多次使用。当前版本每次访问时都会更改参数值。
我现在使用的方法只需要注意__biz参数即可。
我的 采集 系统由以下部分组成:
1、客户端:可以是手机上安装的app,也可以是电脑上的安卓模拟器。经测试,在批处理采集过程中,ios客户端的crash率高于安卓系统。为了降低成本,我使用的是安卓模拟器。
2、个人号码:采集的内容不仅需要客户端,还需要采集专用的个人号码,因为这个号码不能做其他事情。
3、本地代理服务器系统:目前使用的方法是通过Anyproxy代理服务器将历史消息页面中的文章列表发送到自己的服务器上。具体的安装和设置方法将在后面详细介绍。
4、文章列表分析与仓储系统:我用php语言写的。后面会详细介绍如何分析文章列表,建立采集队列,实现批量采集内容。
步
一、安装模拟器或者用手机安装客户端app,申请个人号,登陆app。这个我就不多说了,大家都会的。
二、代理服务器系统安装
目前我正在使用 Anyproxy,AnyProxy。这个软件的特点是可以获取https链接的内容。在 2016 年初开始使用带有 文章 的 https 链接。并且 Anyproxy 可以通过修改规则配置将脚本代码插入页面。让我们从安装和配置过程开始。
1、安装 NodeJS
2、在命令行或者终端运行npm install -g anyproxy,mac系统需要添加sudo;
3、生成RootCA,https需要这个证书:运行命令sudo anyproxy –root(windows可能不需要sudo);————2019年10月28日更新:此行已过期!!!跳过这步
4、启动anyproxy并运行命令:sudo anyproxy -i; 参数 -i 表示解析 HTTPS;
5、安装证书,在手机或安卓模拟器中安装证书:
方法一:启动anyproxy,打开浏览器:8002/fetchCrtFile,可以得到rootCA.crt文件方法二:启动anyproxy,:8002/qr_root可以得到证书路径的二维码,安装起来会更方便移动终端。将证书安装到手机中的代码。
6、设置代理:Android模拟器的代理服务器地址是wifi链接的网关。将dhcp设置为static后可以看到网关地址。阅读后不要忘记将其设置为自动。手机中的代理服务器地址是运行anyproxy的电脑的ip地址。代理服务器的默认端口是8001;
现在打开它,点击任何历史消息或文章,你可以看到响应码在终端滚动。如果没有出现,请检查您手机的代理设置是否正确。
现在打开浏览器地址:8002可以看到anyproxy的网页界面。点击打开历史消息页面,然后查看浏览器的网页界面,历史消息页面的地址会滚动。
以 /mp/getmasssendmsg 开头的 URL 是历史消息页面。左边的小锁表示页面是https加密的。现在让我们点击这一行;
=========2017 年 1 月 11 日更新==========
部件号以/mp/getmasssendmsg开头的URL会有302跳转,跳转到以/mp/profile_ext?action=home开头的地址。所以点击这个地址查看内容。
如果右边出现html文件的内容,则解密成功。如果没有内容,请检查anyproxy的运行模式是否有参数i,是否生成了ca证书,手机上是否正确安装了证书。
现在我们手机上的所有内容都可以以明文形式通过代理服务器。接下来,我们需要修改配置代理服务器,以便获取内容。
一、找到配置文件:
mac系统中配置文件的位置是/usr/local/lib/node_modules/anyproxy/lib/;对于windows系统,不知道的请见谅。应该可以根据类似mac的文件夹地址找到这个目录。
二、修改文件rule_default.js
找到replaceServerResDataAsync: function(req,res,serverResData,callback) 函数
修改函数内容(请详细阅读注释,这里只是原理介绍,了解后根据自己的情况修改内容):
=========2017 年 1 月 11 日更新==========
因为有两种页面形式,同一个页面形式总是以不同的数字显示,但是为了兼容两种页面形式,下面的代码会保留对两种页面形式的判断。您也可以使用自己的页面表单。删除李
php 后面会介绍。res.on(data, function(chunk){callback(chunk+serverResData);//将返回的代码插入到历史消息页面,并返回显示})});}catch(e){//如果是以上正则不匹配,那么这个页面的内容可能是历史消息页面的第二页,因为历史消息的第一页是html格式,第二页是json格式。
try {var json = JSON.parse(serverResData.toString());if (json.general_msg_list != []) {HttpPost(json.general_msg_list,req.url,"getMsgJson.php");//这个函数及以上后面定义一样,将第二页历史消息的json发送到自己的服务器} }catch(e){ console.log(e);//错误捕获}callback(serverResData);//直接返回前两页json内容}}}else if(/mp\/profile_ext\?action=home/i.test(req.url)){//当链接地址为历史消息页时(第二页形式) try { var reg = /var msgList = \(.*?)\;/;//定义历史消息的正则匹配规则(不同于第一页形式) var ret = reg.exec(serverResData.toString()); //转换变量为stringHttpPost(ret[1],req.url,"getMsgJson.php");//这个函数后面定义,
getHis.php的原理后面会介绍。res.on(data, function(chunk){callback(chunk+serverResData);//将返回的代码插入历史消息页面,返回显示})});}catch(e){callback(serverResData); }}else if(/mp\/profile_ext\?action=getmsg/i.test(req.url)){//第二页下页后的jsontry表示{var json = JSON.parse(serverResData.toString( ));if (json.general_msg_list != []) {HttpPost(json.general_msg_list,req.url,"getMsgJson.php");//这个函数后面定义如上,发送第二页历史消息的json到自己的服务器}}catch(e){console.log(e);}callback(serverResData);}else if(/mp\/getappmsgext/i.test(req.url)){//当链接地址是 文章 阅读并喜欢尝试 {HttpPost(serverResData,req.url,"getMsgExt.php");
以上代码使用anyproxy修改返回页面内容的功能,将脚本注入页面,将页面内容发送给服务器。使用此原理来批量 采集 内容和读取量。该脚本中自定义了一个函数,下面详细介绍:
在 rule_default.js 文件的末尾添加以下代码:
function HttpPost(str,url,path) {//向服务器发送json,str为json内容,url为历史消息页地址,path为接收程序的路径和文件名 var http = require( http);var data = {str: encodeURIComponent(str),url: encodeURIComponent(url)};content = require(querystring).stringify(data);var options = {method: "POST",host: "",/ /注意不是,这是服务器的域名。port: 80,path: path,//接收程序头的路径和文件名:{Content-Type: application/x-www-form-urlencoded; charset=UTF-8,"Content-Length": content.length} };var req = http.request(options, function (res) {res.setEncoding(utf8);res.on(data, function (chunk) {console.log(BODY: + chunk);}) ;});req.on(error, function (e) {console.log(problem with request: + e.message);});
以上是规则修改的主要部分。需要将json内容发送到自己的服务器,并从服务器获取跳转到下一页的地址。这涉及到四个php文件:getMsgJson.php、getMsgExt.php、getHis.php、getPost.php
在详细介绍这4个php文件之前,为了提高采集系统性能,降低crash率,我们还可以做一些修改:
Android模拟器经常访问一些地址,会导致anyproxy崩溃,找到函数replaceRequestOption:function(req,option),修改函数内容:
replaceRequestOption : function(req,option){var newOption = option;if(/google/i.test(newOption.headers.host)){newOption.hostname = "";newOption.port = "80";}return newOption; },
以上是anyproxy的规则文件的修改配置。配置修改完成后,重启anyproxy。mac系统下,按control+c中断程序,然后输入命令sudo anyproxy -i启动;如果启动报错,程序可能无法干净退出,端口被占用。此时输入命令ps -a查看被占用的pid,然后输入命令“kill -9 pid”将pid替换为查询到的pid号。杀死进程后,您可以启动anyproxy。或者windows的命令请原谅我不是很熟悉。
接下来详细介绍服务器端接收程序的设计原理:
(以下代码不能直接使用,只是介绍原理,部分需要根据自己的服务器数据库框架编写)
1、getMsgJson.php:该程序负责接收历史消息的json,解析后存入数据库
再次重申,代码只是一个原则,部分观看代码需要自己编写。
2、getMsgExt.php 程序获取文章 浏览量和点赞
3、getHis.php和getPost.php这两个程序类似,一起介绍
=========2017 年 1 月 11 日更新==========
因为有两个页面表示,所以拼接历史消息页面的地址也应该改一下,但是目前即使客户端出现第二个页面表示,也可以发送第一个页面的链接地址,同样有效.
这两个程序的意思是:从队列表中读取下一个采集内容的信息,如果是历史消息页,则将biz拼接到地址中(注:评论区有些朋友认为key 和 pass_ticket 也需要拼接,但不需要),通过js输出到页面。如果下一项是文章,则将历史消息列表json中的文章地址直接输出为js。同理,文章内容的地址不收录uin、key等参数,由客户端自动补充。
这两个程序的细微差别是因为在读取历史消息页面的时候,anyproxy会同时做两件事情,一是把历史消息的json发送给服务器,二是获取链接地址到下一页。但是,这两个操作之间存在时间差。第一次读取下一页的地址时,应该已经获取到当前文章的第一个链接地址,但是此时历史消息的json还没有发送到服务器。,所以只能得到第二个历史消息页。读取第二个历史消息页后得到的下一页的地址是第一个的第一个文章的地址。当队列中还有一条记录时,需要获取下一个链接地址,否则如果队列为空再获取下一个链接地址,就会循环到上面提到的第一次读取。在这种情况下,会有两个历史消息列表,并穿插有文章采集。
刚才四个PHP程序提到了几个数据表,下面说说数据表是怎么设计的。这里只介绍一些主要领域。在实际应用中,会根据不同的程序添加其他必要的字段。
1、表格
CREATE TABLE “(`id` int(11) NOT NULL AUTO_INCREMENT,`biz` varchar(255) DEFAULT COMMENT 唯一 ID biz,`collect` int(11) DEFAULT 1 COMMENT记录采集时间的时间戳,PRIMARY KEY (`id`));
2、文章表格
CREATE TABLE `post` (`id` int(11) NOT NULL AUTO_INCREMENT,`biz` varchar(255) CHARACTER SET utf8 NOT NULL COMMENT 文章对应的biz,`field_id` int (11) NOT NULL COMMENT 定义的 id,每个 文章 唯一,`title` varchar(255) NOT NULL DEFAULT COMMENT 文章 title, `title_encode` text CHARACTER SET utf8 NOT NULL COMMENT 文章 编码防止 文章 出现表情符号,`digest` varchar(500) NOT NULL DEFAULT COMMENT 文章digest,`content_url` varchar( 50< @0) CHARACTER SET utf8 NOT NULL COMMENT 文章Address,`source_url` varchar(500) CHARACTER SET utf8 NOT NULL COMMENT 读取原地址,`cover` varchar(500)@ > CHARACTER SET utf8 NOT NULL COMMENT 封面图片,`is_multi` int(11)NOT NULL COMMENT 是多文本,`is_top` int(11) NOT NULL COMMENT 是标题,`datetime` int (11)NOT NULL COMMENT 文章Timestamp,`readNum` int (11) NOT NULL DEFAULT 1 COMMENT 文章Read amount,`likeNum` int(11) NOT NULL DEFAULT 0 COMMENT 文章 Likes, PRIMARY KEY (`id`) ) ;
3、采集队列列表
CREATE TABLE `tmplist` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`content_url` varchar(255) DEFAULT NULL COMMENT 文章address,`load` int(1< @1) DEFAULT 0 COMMENT 阅读标记,主键(`id`),唯一键`content_url`(`content_url`));
以上是文章批量自动采集系统,由客户端、账号、anyproxy代理服务器、PHP程序、mysql数据库组成。
在下面的文章中,我将进一步详细介绍如何保存文章的内容,如何提高采集系统的稳定性,以及我在运行过程中获得的其他经验。系统。
持续更新,文章批量采集系统构建
文章采集的入口——历史新闻页面详解
文章页面分析和采集
提高文章采集的效率,anyproxy的高级用法