Giter VIP home page Giter VIP logo

wechat-gongzhonghao-crawler's Introduction

wechat-gongzhonghao-crawler(微信公众号爬虫)

这个项目是通过pywinauto控制windows(win10)上的微信PC客户端来实现公众号文章的抓取。代码分成server和client两部分。server接收client抓取的微信公众号文章,并且保存到数据库。另外server支持简单的搜索和导出功能。client通过pywinauto实现微信公众号文章的抓取。

安装和部署

Server的安装

Server由Java实现,理论上可以部署到Client可以访问的任何服务器上,这里假设Server和Client都安装在一台windows 10的机器上。

安装mysql 5.7

用户可以在这里下载mysql,也可以去官网下载,但是请注意:目前只支持5.X版本的mysql。下面介绍在win10上安装的过程。

安装

执行下载msi的安装文件,在"Choosing a Setup Type"里选择"Server only"。 然后点击next安装。安装完了需要配置。

mysql配置

"Type and Networking",可以选择"Development Computer",如果机器的资源比较丰富,也可以选择"Server Computer"。 "Accounts and Roles"设置root密码。 "Windows Service"使用默认设置。

修改utf8编码

找到mysql服务的配置文件地址,可以在搜索栏输入"服务",然后找到mysql服务,右键点击属性,找到mysql配置文件的位置,如下图所示:

图中显示配置文件的位置为"C:\ProgramData\MySQL\MySQL Server 5.7\my.ini",修改这个文件,加入:

[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
init-connect='SET NAMES utf8mb4'
collation_server=utf8mb4_unicode_ci
character_set_server=utf8mb4
character-set-server=utf8mb4

注意:我们需要找到my.ini文件下面的[client],然后把default-character-set=utf8mb4加到它的下面。类似的,在[mysql]和[mysqld]下面加入那些内容。 注意:不能直接把上面的文本复制到mysql.ini文件。ini文件是用"[client]"分成不同的部分的。 修改后重启服务,如下图所示:

可以用下面的sql命令检查配置是否正确:

mysql> SHOW GLOBAL VARIABLES WHERE Variable_name LIKE 'character_set_%' OR Variable_name LIKE 'collation%';

结果应该是:

+--------------------------+--------------------+
| Variable_name            | Value              |
+--------------------------+--------------------+
| character_set_client     | utf8mb4            |
| character_set_connection | utf8mb4            |
| character_set_database   | utf8mb4            |
| character_set_filesystem | binary             |
| character_set_results    | utf8mb4            |
| character_set_server     | utf8mb4            |
| character_set_system     | utf8               |
| collation_connection     | utf8mb4_unicode_ci |
| collation_database       | utf8mb4_unicode_ci |
| collation_server         | utf8mb4_unicode_ci |
+--------------------------+--------------------+
10 rows in set (0.00 sec)
建表

在开始菜单寻找"Mysql 5.7 Command Line Client - Unicode",点击后命令行执行 mysql -u root -p,输入root密码后执行下面的命令:

# run as root
CREATE DATABASE `wechat`;
CREATE USER 'wechat'@'localhost' IDENTIFIED BY 'mypass';
GRANT ALL PRIVILEGES ON wechat.* TO 'wechat'@'localhost';
FLUSH PRIVILEGES;

如果需要,也可以修改wechat的密码为其它值,但是后面的配置文件也需要设置成对应的密码。 然后exit退出,然后用wechat账号重新登录:mysql -u wechat -p,并创建表:

use wechat;
CREATE TABLE `webpage` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `url` varchar(512) NOT NULL,
  `title` varchar(1024) NOT NULL,
  `pub_name` varchar(128) NOT NULL,
  `pub_time` datetime DEFAULT NULL,
  `html` mediumblob,
  `content` mediumtext,
  `last_update` datetime DEFAULT NULL,
  `crawl_wechat_id` varchar(128) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `url` (`url`),
  KEY `last_update` (`last_update`),
  KEY `pub_name` (`pub_name`),
  KEY `crawl_wechat_id` (`crawl_wechat_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;


CREATE TABLE `state` (
  `id` int NOT NULL,
  `url` varchar(512) NOT NULL,
  `pub_name` varchar(128) NOT NULL,
  `title` varchar(1024) NOT NULL,
  `crawl_state` tinyint NOT NULL, # 1: 未抓取网页, 0: 抓取成功, 2: 失败1次 3: 失败2次,...
  `counter_state` tinyint NOT NULL, # 1: 未更新计数, 0: 更新成功, 3: 失败1次 ....
  `first_add` datetime NOT NULL,
  `last_update` datetime NOT NULL,
  `sync_page` tinyint NOT NULL, # 0 未同步,1已同步
  `sync_counter` tinyint NOT NULL,
  PRIMARY KEY (`id`),
  KEY `pub_name` (`pub_name`),
  KEY `crawl_state` (`crawl_state`),
  KEY `counter_state` (`counter_state`),
  KEY `sync_page` (`sync_page`),
  KEY `sync_counter` (`sync_counter`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

CREATE TABLE `heartbeat` (
  `crawl_wechat_id` varchar(128) NOT NULL,
  `activity_type` varchar(256) NOT NULL,
  `last_update` datetime NOT NULL,
  PRIMARY KEY (`crawl_wechat_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;


CREATE TABLE `debuginfo` (
  `crawl_wechat_id` varchar(128) NOT NULL,
  `content` MEDIUMTEXT,
  PRIMARY KEY (`crawl_wechat_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

阅读数的表:

CREATE TABLE `counter` (
  `id` int(11) NOT NULL,
  `read_count` int DEFAULT -1,
  `last_update` datetime NOT NULL,
  `crawl_wechat_id` varchar(128) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

如果用户从v1.0升级到v1.1,则只需要新增counter表就行。

升级到v1.2:

ALTER TABLE `counter`
ADD COLUMN `star_count` int DEFAULT -1,
ADD COLUMN `share_count` int DEFAULT -1;

如果用户从v1.1升级到v1.2,只需要执行上面的命令就行。

安装JDK并启动服务

用户可以在这里下载JDK,或者根据自己的机器选择其它版本的JDK。安装后需要设置环境变量,确保可以通过cmd运行Java。

jdk的安装使用默认选项就可以。启动命令行,输入java确认安装成功。如果找不到请设置PATH环境变量,具体可以上网搜索。 在release下载最新版本的wechat-crawler-server-...-jar-with-dependencies.jar。把这个jar包放到某个文件夹下,然后在这个文件夹下创建一个conf的目录。在conf下新建一个dbConf.properties配置文件,然后修改其内容:

MYSQL_DRIVER=org.gjt.mm.mysql.Driver
MYSQL_URL=jdbc:mysql://localhost:3306/${db}
MYSQL_USER=wechat
MYSQL_PASS=mypass

主要是修改密码。

然后在命令行执行:

java -cp wechat-crawler-server-{VERSION}-jar-with-dependencies.jar com.github.fancyerii.wechatcrawler.server.service.WechatCrawlerServer

请修改{VERSION}为实际文件的值。

Client的安装

安装和登录微信

请下载的微信安装程序安装,安装完成后参考这篇文章禁止微信自动升级,然后扫码登录。请读者使用3.1版本的微信客户端,因为版本升级或者变化可能导致代码无法正常运行。

系统设置

因为爬虫的工作原理是控制微信,所以需要去掉windows的自动锁屏功能。具体方法可以参考这篇文章

安装tesseract

v1.1新增,如果需要抓取阅读数需要安装它。安装方法参考这里,请记得确认安装的路径是“C:\Program Files\Tesseract-OCR\tesseract”,目前的代码还不能配置这个路径。

设置客户端

首先去release下载最新版本的cli.exe,把它放到某个目录下,然后在这个目录创建config.ini文件和gongzhonghao.txt两个文件。config.ini可以参考这个:

[basic]
java_server = http://127.0.0.1:4567
max_crawl_pages = 3
win_width = 1000
win_height = 600
lock_input = False
first_pages = 30
latest_date = 2021-01-01
first_max_crawl_time = 3600
switch_gongzhonghao = 北京动物园

主要配置说明:

  • lock_input
    • 它的作用是锁定屏幕,从而保证系统安全
  • max_crawl_pages
    • 更新时(不包括第一次抓取)最多往前翻页数量
  • first_pages
    • 第一次抓取时最大的翻页数量
  • latest_date
    • 第一次抓取时的最早日期,这个条件和前面的first_pages哪个满足都会跳出第一次抓取
  • switch_gongzhonghao
    • 由于抓取的原理,则需要通过切换账号才能实现得到最新的文章,如果在gongzhonghao.txt里只配置了一个公众号,则需要配置用于“切换”刷新的公众号。
  • first_max_crawl_time
    • 单位是秒。为了避免第一次刷新的时间过程,这个参数会让代码跳出循环。比如有10个公众号,假设每个公众号第一次抓取要一天。如果没有这个设置,那么第一次抓取可能会需要10天,当第一次结束后默认更新时只抓取3页,那么如果某个公众号在10天里更新超过3页,就有可能漏过。配置了这个参数上之后,比如抓取第一个公众号的第一次需要1天,它超过了3600s,则会跳出循环,然后再次循环,再次抓取公众号1,这会很快,然后第一次抓取公众号2,花一天时间,然后又退出;然后再次抓取公众号1和2,然后又花一天抓取公众号3,……,这样就能保障不会漏抓。
  • crawl_read_count
    • v1.1新增,默认为False。如果需要抓取阅读数,则需要设置为True
  • counter_interval_seconds
    • v1.1新增,默认为172800(两天)。表示当前距离文章的发布时间超过它(两天)才抓取阅读数
  • no_item_retry
    • v1.3.4新增,默认3。列表页翻页失败最多重试次数

配置公众号

为了告诉爬虫抓取哪些公众号,需要在gongzhonghao.txt里配置要抓取的公众号名(注意是名字而不是id)。 比如:

环球科学
北京海淀

注意:PC客户端无法实现关注公众号的功能,我们需要手动在手机微信里关注这些公众号!!!!

启动爬虫

首先通过手机扫描登录微信PC客户端,然后双击cli.exe运行。请关注命令行的输出,如果有错误信息请通过issue反馈,请详细描述问题并且导出调试信息。获取调试信息参考下面。

调试信息

请执行如下命令收集信息反馈给开发者:

java -cp wechat-crawler-server-xxx-jar-with-dependencies.jar com.github.fancyerii.wechatcrawler.server.service.DumpDebugInfo debug-info.txt

请把debug-info.txt发送给开发者进行诊断。

查看抓取数据

使用浏览器打开这里,就可以搜索公众号文章,下方的【下载JSON】链接也可以导出下载的文章。UI比较丑陋,欢迎大家发pull request改进ui。

开发者

clone代码

因为在tools里有微信和mysql等很大的安装程序,是通过LFS存储的。如果直接clone会很慢而且没有必要,可以设置环境变量GIT_LFS_SKIP_SMUDGE=1来忽略它们:

GIT_LFS_SKIP_SMUDGE=1 git clone https://github.com/fancyerii/wechat-gongzhonghao-crawler.git
cd wechat-gongzhonghao-crawler

编译Server代码

$ cd server
$ mvn compile assembly:single

编译后的jar包在target/wechat-crawler-server-1.0-jar-with-dependencies.jar,它包含了所有的依赖。

Client代码

安装依赖:

pip install -r requirements.txt

然后直接运行cli.py即可。

Client打包成exe文件

需要安装pyinstaller:

pip install pyinstaller

然后用pyinstaller打包:

cd client
pyinstaller.exe --onefile cli.py

如果是python3.6的话可能会出现“The win32ui module could not initialize the application object”的错误,参考这篇文章,可以协助300版本安装228:

pip uninstall pywin32
pip install pywin32==228

把本地抓取的数据同步到中心服务器

如果抓取的微信公众号特别多,那么可能我们会部署多台服务器进行抓取。按照默认配置,每台机器抓取的结果都保存在本地的mysql中。当然我们可以写一些脚本把这些数据进行汇总,但是仍然有一些逻辑需要考虑,比如增量同步等等。为了避免这些麻烦,本项目提供了数据同步的功能。

为了实现这个功能,需要有一台可以被抓取服务器访问的中心服务器,我们这里假设中心服务器的域名为center_server(如果没有域名可以改成外网ip)。

中心服务器建表

我们首先在中心服务器的mysql上建立wechat数据库,设置用户名和密码。然后建立如下表:



use wechat;

CREATE TABLE `all_pages` (
  `url` varchar(512) NOT NULL,
  `title` varchar(1024) NOT NULL,
  `pub_name` varchar(128) NOT NULL,
  `pub_time` datetime DEFAULT NULL,
  `html` mediumblob,
  `content` mediumtext,
  `last_update` datetime DEFAULT NULL,
  `crawl_wechat_id` varchar(128) DEFAULT NULL,
  PRIMARY KEY (`url`),
  KEY `last_update` (`last_update`),
  KEY `pub_name` (`pub_name`),
  KEY `crawl_wechat_id` (`crawl_wechat_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

CREATE TABLE `all_counters` (
  `url` varchar(512) NOT NULL,
  `read_count` int DEFAULT 0,
  `star_count` int DEFAULT 0,
  `last_update` datetime NOT NULL,
  `crawl_wechat_id` varchar(128) NOT NULL,
  `rvs` mediumblob,
  PRIMARY KEY (`url`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

CREATE TABLE `wechat_pass` (
  `wechat_id` varchar(128) NOT NULL,
  `pass` varchar(64) NOT NULL,
  PRIMARY KEY (`wechat_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

升级到v1.2:

ALTER TABLE `all_counters` ADD COLUMN `share_count` int DEFAULT 0;

启动中心服务器的数据接受服务

修改配置文件conf/cfg.txt:

salt=chan_search
iv=3FZEMcOdhXdXsYgQZR7LPw==
clear_pass=12345

参数salt和iv是加密用的,可以修改,但是下面Java Server的配置文件需要使用相同的值。clear_pass是通过远程的方式清除缓存密码的密码,这是远程(非本地)可以访问的,一定要修改为一个安全的密码。

nohup java -cp wechat-crawler-server-1.1-SNAPSHOT-jar-with-dependencies.jar com.github.fancyerii.wechatcrawler.server.service.WechatSyncServer 2>&1 &

为客户端创建用户名和密码

为了安全考虑,客户端往中心服务器同步数据时会进行加密。因此需要在wechat_pass表里为客户端建立密码:

insert into wechat_pass values('wechat_id', 'pass');

注意:我们需要把wechat_id替换成Windows客户端登录的微信id;密码改成一个安全的密码。这个密码在后面的配置中会用到。

Java Server设置

在cfg.txt里设置:

server_url=http://center_server:7654
do_sync=true

wechat_id=....
enc_pass=
salt=chan_search
iv=3FZEMcOdhXdXsYgQZR7LPw==

配置说明:

  • server_url
    • 设置中心服务器的url,前面的WechatSyncServer默认会监听在7654端口。
  • do_sync
    • 设置为true时,Java Server会定期同步数据到中心服务器。否则不同步数据。
  • wechat_id
    • cli.exe抓取时使用的微信id。
  • enc_pass
    • 前面在中心服务器配置的密码。
  • salt
    • 和中心服务器一致
  • iv
    • 和中心服务器一致

设置后重启服务。注意:如果cli.exe还在执行,重启Java Server可能会丢失数据,因此建议等cli.exe在没有抓取或者关闭cli.exe后重启。

客户端代码介绍

请参考使用pywinauto驱动微信客户端实现公众号抓取

FAQ

抓取的时候电脑为什么干不了别的事情?

因为抓取的原理是通过鼠标键盘来控制PC版的微信客户端,它需要成为桌面的焦点,而且如果用户操作鼠标或者键盘,可能会导致控制失败。要解决这个问题可以安装虚拟机,在虚拟机里面跑这个代码,而且虚拟机随时可以最小化甚至锁屏。

抓取的时候为什么不能锁屏,这样是不是很危险?

因为抓取的原理,如果锁屏的话程序就无法控制危险客户端,从而也就无法抓屏了。如果是在自己家里,应该风险不大。如果是在办公室里,建议配置lock_input=true,这样程序会锁定鼠标和键盘。锁定后我们可以使用【win+L】解除锁定并且锁屏,然后输入密码解锁。另外如果是台式机的话,建议抓取的时候关掉显示器,这样是不会影响抓取的。笔记本合上机盖可能会锁屏,读者可以搜索自己的笔记本品牌看看是否能够盒盖但是不锁屏。

另外的解决方法就是在虚拟机里跑这个程序。

能够抓取阅读数量等信息吗?

v1.1版本实现了阅读数的抓取。

能够抓取服务号的文章吗?

v1.3版本实现了服务号的抓取。

怎么开多个微信同时抓取?

目前程序只支持一个微信,即使用hack的方法多开微信也不行。为了提高抓取速度,可以在一台机器上安装多个虚拟机,每个虚拟机跑一个微信。注意,如果是这种模式,可以把mysql安装在一个共享的地方,从而避免每个虚拟机都安装一个mysql(当然不嫌麻烦也没问题)。

我的操作系统不是Windows怎么办?

请在虚拟机里安装win10。

wechat-gongzhonghao-crawler's People

Contributors

fancyerii avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

wechat-gongzhonghao-crawler's Issues

安装JDK并启动服务出现问题

您好,想请问您一下出现

错误: 找不到或无法加载主类 com.github.fancyerii.wechatcrawler.server.service.WechatCrawlerServer

应该如何解决?

求助,是否需要保持微信客户端始终保持在前台?

求助,是否需要保持微信客户端始终保持在前台?
我看pywinauto的文档,好像说道click方法并不需要程序界面保持可见状态的,但是实验下来发现必须保持课件才行,不知道大佬有没有遇到这个情况。

initDataSource时报NPE

java -cp wechat-crawler-server-1.3.2-jar-with-dependencies.jar com.github.fancyerii.wechatcrawler.server.service.WechatCrawlerServer
2024-04-11 17:00:17.022 [main] INFO s.s.StaticFilesConfiguration - StaticResourceHandler configured with folder = /public
Exception in thread "main" java.lang.NullPointerException
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at com.antbrains.mysqltool.PoolManager.initDataSource(PoolManager.java:95)
at com.antbrains.mysqltool.PoolManager.StartPool(PoolManager.java:144)
at com.github.fancyerii.wechatcrawler.server.service.WechatCrawlerServer.main(WechatCrawlerServer.java:28)

已经按照说明在conf/dbConf.properties配置好
MYSQL_DRIVER=org.gjt.mm.mysql.Driver
MYSQL_URL=jdbc:mysql://localhost:3306/wechat
MYSQL_USER=wechat
MYSQL_PASS=mypass

抓取过程中出错

抓取过程中, 第一次存完库 报错:
Traceback (most recent call last):
File "cli.py", line 54, in
File "crawler_main_.py", line 340, in main
File "crawler\wechatautomator.py", line 68, in get_wechat_id
UnboundLocalError: local variable 'wechat_id' referenced before assignment
[11688] Failed to execute script cli

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.