$ python3 bootstrap-buildout.py //执行工程目录下的bootstrap-buildout.py, 初始化buildout
$ bin/buildout //安装依赖,构建项目
- open Preference -> Build, Execution, Deployment -> Buildout Support -> Enable buildout support
- 将bin目录下的bs4添加进Path.
- p.s. bin/bs4 is generated by buildout
- 启动Redis(默认端口6379)
- 启动mysql, 新建stackshare库, 新建表「companies」「stacks」
- 数据库配置详见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
- 统一在参数的 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/
-
PyRedis 获取出的数据为 byte 类型,需手动转换..
-
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
-
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 : 未深究源码, 不知理解是否偏差,若有错误还望指教~