陈文管:微信公众号文章服务端数据采集系统

优采云 发布时间: 2021-08-26 22:15

  

陈文管:微信公众号文章服务端数据采集系统

  

  本文转载自:陈文冠博客-微信公众号文章攀取之:服务端数据采集本文介绍微信公众号文章服务端数据爬取的实现,结合上一篇微信公众号文章采集之:微信自动化构成了一个完整的微信公众号文章数据采集系统。

  

  公众号文章crawling 系统架构图

  一、AnyProxy 配置(Mac)

  AnyProxy是一个开放的HTTP代理服务器,官方文档:Github主页:主要特点包括:基于Node.js,开放二次开发能力,允许自定义请求处理逻辑,支持Https分析,提供观察请求的GUI界面

  1、Install NodeJS

  在安装Anyproxy之前,需要先安装Nodejs。 Nodejs下载地址:。下载安装后,可以在终端执行以下命令查看安装的版本:

  1

2

   node --version       查看node安装版本

npm -v               查看npm安装版本

  2、AnyProxy 安装配置1)Mac端安装配置

  不要安装最新版本的AnyProxy,因为界面变化很大,在原来的基础上改写界面不方便。如果已经安装了最新版本,请先执行以下命令卸载:

  1

  sudo npm uninstall -g anyproxy

  稍后安装3.X 版本:

  1

  sudo npm install  anyproxy@3.x  -g

  然后安装相应的证书:

  1

  anyproxy --root

  2) AnyProxy rule_default.js 文件配置

  直接复制以下配置覆盖AnyProxy rule_default.js配置文件。详情请参考知乎大神的文章:微信公众号内容采集及应用,包括图片优化和配置将fs.readFileSync()参数替换为自己的图片放置路径。将公众号中的所有图片替换为本地图片的目的是为了减少网络传输压力和浏览器占用的内存,有效提高运行效率。你可以自己制作一张1×1像素的png透明图片。这里和知乎文章的区别在于,在replaceServerResDataAsync中,只需要将截获的微信文章URL地址转发到自己的服务器即可,因为自动浏览脚本直接进入公众号文章详情页不需要像知乎文章 介绍的那么麻烦。 TIPS:2019.5.6-2019.5.12时间段,微信公众号更新了公众号文章的请求加载方式。在 replaceServerResDataAsync 接口中拦截 URL 的方式不再可行。通过AnyProxy截获的URL参数,可以看到没有以“/s?__biz=”开头的URL,而是来自

  1

  “/mp/getappmsgext?”和“/mp/getappmsgad?“

  点击开头的请求链接依然可以看到文章的请求链接地址。如果是2019.5.12之前的时间,拦截URL接口在replaceServerResDataAsync,对应的AnyProxy rule_default.js配置文件是:rule_default_before20190512.js 2019.5.之后的时间12点,截取URL的接口改为shouldUseLocalResponse: function(req,reqBody),只需要将请求体发送到后端服务器,加上""前缀进行拼接即可。对应的AnyProxy rule_default.js配置文件应该改为:rule_default_after20190512.js 如果忘记AnyProxy的安装路径,使用命令查找rule_default.js文件:

  1

  find ~ -iname "rule_default.js"

  3)AnyProxy 启动

  在终端执行命令启动AnyProxy:

  1

  anyproxy -i

  如果遇到如下异常,说明你没有权限写入文件夹:

  1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

  the default rule for AnyProxy.

Anyproxy rules initialize finished, have fun!

The WebSocket will not work properly in the https intercept mode :(

fs.js:885

  return binding.mkdir(pathModule._makeLong(path),

                 ^

Error: EACCES: permission denied, mkdir '/Users/chenwenguan/.anyproxy/cache_r929590'

    at Object.fs.mkdirSync (fs.js:885:18)

    at Object.module.exports.generateCacheDir (/Users/chenwenguan/.nvm/versions/node/v8.9.3/lib/node_modules/anyproxy/lib/util.js:54:8)

    at new Recorder (/Users/chenwenguan/.nvm/versions/node/v8.9.3/lib/node_modules/anyproxy/lib/recorder.js:16:31)

    at /Users/chenwenguan/.nvm/versions/node/v8.9.3/lib/node_modules/anyproxy/proxy.js:116:43

    at ChildProcess.exithandler (child_process.js:282:5)

    at emitTwo (events.js:126:13)

    at ChildProcess.emit (events.js:214:7)

    at maybeClose (internal/child_process.js:925:16)

    at Socket.stream.socket.on (internal/child_process.js:346:11)

    at emitOne (events.js:116:13)

  使用以下命令修改文件夹权限:

  1

  sudo chown -R `whoami` /Users/chenwenguan/.anyproxy

  4)Android 虚拟机上的配置

  AnyProxy启动完成后,访问GUI地址:8002

  

  下载 AnyProxy 证书文件

  点击下载rootCA.crt文件,可以在虚拟机的sd卡​​根目录下创建rootCA文件夹,使用adb命令将文件push到虚拟机的sdcard目录下:

  1

  adb push rootCA.crt /sdcard/rootCA/

  进入Android虚拟机系统设置界面后,进入安全设置项,选择install from SD card(从SD卡安装证书)设置项,选择Push安装SD卡下的证书文件,如果这样做不要这样做,在微信加载WebView时,会不断弹出警告弹窗。如果在模拟器中没有找到系统设置或者WI-FI网络设置的入口,可以使用adb命令调用进入,直接进入网络设置页面。命令如下:

  1

  adb shell am start -a android.intent.action.MAIN -n com.android.settings/.wifi.WifiSettings

  进入模拟器系统设置页面命令:

  1

  adb shell am start com.android.settings/com.android.settings.Settings

  您还需要在 Android 模拟器上设置网络代理。长按WIFI网络设置项,在弹出的窗口中选择修改网络选项。 IP地址是电脑的IP,端口是8001。

  

  Android 虚拟机网络代理设置

  以上配置完成后,进入微信应用查看公众号文章,在GUI界面可以看到AnyProxy截获的所有请求URL地址信息。正如上面文章所解释的,在2019.5.12之前也可以看到以“/s?__biz=”开头的URL请求参数。

  

  AnyProxy 截获的 URL 信息

  以上/s?__biz=开头的网址为微信公众号文章的详细网址,具体可点击查看:

  

  微信公众号文章URL详细信息

  页面向下滑动查看所请求公众号文章的详细字段信息。服务器爬虫从这些字段参数定义的值中截取需要的信息。

  

  公众号文章AnyProxy解析的详细信息

  目前服务器上保存的字段只是一些基本信息,如标题、作者、文章发布时间等,如果需要其他信息,可以参考上图中部分字段进行正则匹配. 2015.5.12,微信改变公众号文章的加载方式后,文章的实际地址参数在“/mp/getappmsgext?”开头的请求链接中,包括喜欢和阅读数据也在这个请求返回的结构中。 “/mp/getappmsgad?”开头的请求链接的请求正文也是文章的链接地址,不过最好选择以“/mp/getappmsgext?”开头的URL拦截它。

  

  拦截getappmsgext的请求结构为文章real地址

  在getappmsgext截获的页面往下滑动到响应正文可以看到文章的阅读点赞数据,因为阅读点赞没有数据分析要求,所以有需要的可以研究一下由 rule_default 自己完成。 js配置文件的哪个接口拦截转发数据。

  

  拦截getappmsgext请求返回的数据包括阅读次数和点赞次数

  二、JavaWeb服务器实现1、运行环境配置

  Intellij IDEA官网下载地址:破解方法参考:IntelliJ IDEA 2017完美注册方法TIPS:必须先打开IDEA再进行如下配置,否则会被识别为文件损坏

  1

  -javaagent:/Applications/IntelliJ IDEA.app/Contents/bin/JetbrainsCrack-2.7-release-str.jar

  2、Server 实现

  爬虫服务器实现GitHub源码地址:

  1

  [https://github.com/wenguan0927/WechatSpider](https://github.com/wenguan0927/WechatSpider)

  1)实现类说明

  

  公众号爬虫服务器源码实现说明

  WechatController类做AnyProxy转发的文章链接接收和JSP页面显示的逻辑处理。 mapper文件夹下的两个类是数据库操作的映射操作类,由配置文件自动生成,但是手动添加了几个数据查询方法。 PostKeyWordMapper用于对公众账号文章关键词的数据进行操作和存储。 WechatPostMapper 用于操作和存储公众号文章的详细数据。模型文件夹中的 PostJSP 只是一个中间类,用于在 JSP 页面上显示数据。在JSP页面中拼接含有较多特殊字符的文本内容时很容易出现问题。我这里的实现是直接生成MarkDown文档的格式,所以做了一层转换。 PostKeyWord为公众号关键词分类,WechatPost为公众号文章详细数据分类。 Spider文件夹下的类是公众号文章keyword和公众号文章详细信息的爬取解析类。 util文件夹收录工具类,SimHash仅用于测试通过关键字计算公众账号文章相关度的实现类。有兴趣的可以自行挖掘。

  2)配置文件说明

  

  公众号爬虫服务器配置文件实现说明

  mybatis-mapper文件夹中的两个文件是数据库映射XML资源文件,由两个配置文件generator.properties和generatorConfig.xml自动生成。详情请参考:数据库表反向生成(一)MyBatis-*敏*感*词*和IDEA的集成。这里需要注意的是,如果要在反向生成的数据库映射操作文件中添加方法实现,不要添加Mapper.xml 文件中的方法,如果要添加,添加到 Mapper.java 类中,可以通过在函数中添加注解来引用 WechatPostMapper.java 类末尾的方法。将generator.properties文件中的.driverLocation改为你电脑上connector的实际路径,jdbc.userId和jdbc.password改为你自己数据库的用户名和密码jdbc.properties中的数据库参数文件也改为自己配置的值,其他文件只是常规的Web实现配置,这里不再赘述。

  3)实现过程中遇到的问题

  1)@Autowired 带注解的 Mapper 类报告 NullPointException 异常

  1

2

3

4

      @Autowired

    private WechatPostMapper wechatPostMapper;

    @Autowired

    private PostKeywordMapper postKeywordMapper;

  这里需要注意的是,通过@Autowired注解声明的类不能在新的类中使用。 @Autowired 只能在通过框架注解生成的类中使用。该注解在新类中使用框架生成的类没有找到,所以会报空指针异常。其他异常可以参考:@Autowired注解和静态方法2)Intellj(IDEA)警告没有配置工件异常参考文章:[错误解决]Intellj(IDEA)警告没有配置工件3)Intellij代理端口占用异常

  1

2

3

  错误: 代理抛出异常错误:

java.rmi.server.ExportException: Port already in use: 1099; nested exception is: 

java.net.BindException: Address already in use

  输入终端命令查看端口进程:

  1

  sudo lsof -i :1099

  之后,您可以看到类似的结果,如下所示:

  1

2

  COMMAND PID        USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME

java    582 chenwenguan   23u  IPv6 0x38b6c6251709a7d3      0t0  TCP *:rmiregistry (LISTEN)

  输入终端命令杀死进程:kill 582 4)无法解析 如果配置的jstl版本为1.2,则无需导入jstl.jar和standard.jar包,如果配置1. 2 以下版本请参考文章:核心无法解析。 jar包下载地址:

  1

  [http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/](http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/)

  5)警告:/usr/local/mysql/data 目录不属于‘mysql’或‘_mysql’

  如果MySQL由于Mac系统更新提示上述异常,执行如下命令解决:

  1

  sudo chown -R  _mysql:wheel  /usr/local/mysql/data

  参考博文:在偏好设置6)Mac上启动MySQL失败@数据库IN查询语句实现的注解

  1

2

3

4

5

6

7

8

9

10

11

12

13

14

  @Select({"",

         "select",

         "id, biz, appmsgid, title, digest, contenturl, sourceurl, cover, datetime, readnum, ",

         "likenum, isspider, author, nickname, weight, posttype, content",

         "from postTable where nickname in ",

         "",

         "#{item}",

         "",

         " and datetime >=#{datetime,jdbcType=TIMESTAMP}",

         "order by weight DESC",

         ""

})

@ResultMap("ResultMapWithBLOBs")

List getATAPosts(@Param("nickname") List nickname, @Param("datetime") Date time);

  如果要在注解中实现IN多条件查询,需要按照上面的方式实现,直接用原生SQL语句的方式实现是行不通的。参考博文:SpringBoot使用Mybatis注解开发教程-分页-动态sql

  4) 数据库实现

  公众号文章详细数据表实现:

  1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

  CREATE TABLE `postTable` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `biz` tinytext,

  `appmsgid` tinytext,

  `title` tinytext,

  `digest` longtext,

  `contenturl` longtext,

  `sourceurl` longtext,

  `cover` longtext,

  `datetime` datetime DEFAULT NULL,

  `readnum` int(11) DEFAULT NULL,

  `likenum` int(11) DEFAULT NULL,

  `isspider` int(11) DEFAULT NULL,

  `author` tinytext,

  `nickname` tinytext,

  `weight` int(11) DEFAULT NULL,

  `posttype` int(11) DEFAULT NULL,

  `content` longtext,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=199 DEFAULT CHARSET=utf8

  公众号关键字数据表的实现:

  1

2

3

4

5

6

7

  CREATE TABLE `keywordTable` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `wordtext` varchar(45) DEFAULT NULL,

  `wordfrequency` int(11) DEFAULT NULL,

  `wordtype` int(11) DEFAULT NULL,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=3525 DEFAULT CHARSET=utf8

  5)legacy 问题

  公众号文章的分类目前还没有很好的实现,即目前爬取的公众号文章将分为三类,新闻、Android开发、技术拓展、初步构想它根据过去发布的每周技术周报文章的内容,提取每个类别文章的关键词数据,生成关键词数据库。后面爬取的文章可以通过提取文章的@将关键词与历史记录文章的关键词词库进行比较,计算它们的相关性进行分类。 HanLP 开源代码目前用于测试。提取的关键词都是中文的关键词。在做相关性计算的时候,无法达到预期的效果,因为开发文章有很多英文词汇,HanLP不包括英文词汇的词库,所以下一步就是搭建一个技术性的文章词——切分词库实现文章的分类。以下是指向文章 的资源的一些链接。有兴趣的可以自己深入了解一下。

  三、其他参考资料

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线