Skip to content
/ crawler Public
forked from zeng-tong/crawler

A crawler to collect stackshare's information.

Notifications You must be signed in to change notification settings

zjuyxy/crawler

 
 

Repository files navigation

自建版 Build Status

安装依赖

$ python3 bootstrap-buildout.py //执行工程目录下的bootstrap-buildout.py, 初始化buildout
$ bin/buildout //安装依赖,构建项目

Pycharm Setting

  • open Preference -> Build, Execution, Deployment -> Buildout Support -> Enable buildout support
  • 将bin目录下的bs4添加进Path.
  • p.s. bin/bs4 is generated by buildout

本地运行前需初始化:

  1. 启动Redis(默认端口6379)
  2. 启动mysql, 新建stackshare库, 新建表「companies」「stacks」
  3. 数据库配置详见cofig.py
CREATE TABLE `companies` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(256) NOT NULL DEFAULT '',
  `description` varchar(256) DEFAULT '',
  `logo` varchar(256) NOT NULL DEFAULT '',
  `site` varchar(256) DEFAULT NULL,
  `token` varchar(256) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `stacks` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(256) DEFAULT NULL,
  `contents` varchar(256) DEFAULT NULL,
  `description` varchar(256) DEFAULT NULL,
  `star_count` varchar(11) DEFAULT NULL,
  `votes_count` varchar(11) DEFAULT NULL,
  `fans_count` varchar(11) DEFAULT NULL,
  `stacks_count` varchar(11) DEFAULT NULL,
  `integrations_count` varchar(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

启动

  • p.s: 启动之前,必须安装依赖.

  • 获取待爬取 id 并存入redis:

    • bin/bs4 stackshare/main.py -p
    • bin/bs4 stackshare/main.py --producer
  • 从 redis 中获取 id 并爬取数据:

    • bin/bs4 stackshare/main.py -s
    • bin/bs4 stackshare/main.py --consumer
  • 获取公司名及logo:

    • bin/bs4 stackshare/main.py -c
    • bin/bs4 stackshare/main.py --companies

Hint

  • 统一在参数的 URL 前加 : "/" , 代码里的 DOMAIN 结尾默认都无 "/"
  • pycharm 运行请注意 Working directory为 crawler 而不是 crawler/stackshare
  • 存入数据库的信息中,可能存在 emoji 表情. 为避免插入失败数据库编码设置为utf8mb4 参见: How to store Emoji Character in My SQL Database
  • MySQL: root:123456@139.59.229.154/stackshare?charset=utf8 云主机数据库已移除

Pyspider 版:

文件位置

pyspider/

采坑记录

  1. PyRedis 获取出的数据为 byte 类型,需手动转换..

  2. Logging 输出日志有重复的数据.原因:

    loggers 就是程序可以直接调用的一个日志接口,可以直接向logger写入日志信息。logger并不是直接实例化使用的,而是通过logging.getLogger(name)来获取对象,事实上logger对象是单例模式,logging是多线程安全的,也就是无论程序中哪里需要打日志获取到的logger对象都是同一个。但是不幸的是logger并不支持多进程,这个在后面的章节再解释,并给出一些解决方案。 【注意】loggers对象是有父子关系的,当没有父logger对象时它的父对象是root,当拥有父对象时父子关系会被修正。举个例子logging.getLogger("abc.xyz")会创建两个logger对象,一个是abc父对象,一个是xyz子对象,同时abc没有父对象所以它的父对象是root。但是实际上abc是一个占位对象(虚的日志对象),可以没有handler来处理日志。但是root不是占位对象,如果某一个日志对象打日志时,它的父对象会同时收到日志,所以有些使用者发现创建了一个logger对象时会打两遍日志,就是因为他创建的logger打了一遍日志,同时root对象也打了一遍日志。 来源简书 作者:doudou0o

  3. pyspider 的 crawl 函数,经调试发现相同 URL 只请求一次。即是若两个 crawl 函数请求的 URL 相同,则完成第一个 crawl 函数之后,第二个 crawl 函数不会再被调用。

# 每次请求的 URL 不同,可正常工作 
for each in div.find_all('a'):
            self.crawl(URL + each['href'], callback=self.get_item) 
            
# 每次请求的 URL 相同, 即便 payload 不一样,也不能正常工作,只能完成第一次请求.
while _id:
    _id = int(_id)
    payload = {'ids[]': _id}
    self.crawl(response.url + '/load-more', data=payload, method='POST', callback=self.get_item)
    redis.sadd(consumedKey(response.persist['category']), _id)
    _id = redis.rpop(response.persist['category'])

# p.s : 未深究源码, 不知理解是否偏差,若有错误还望指教~

About

A crawler to collect stackshare's information.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 100.0%