Scrapy豆瓣ADHD小组爬虫实例

前言

搞这玩意让自己熟悉数据资源获取->数据持久化并整理->数据可视化的数据处理流程,顺便记录下Scrapy的框架的使用过程。

基本思路

数据获取及持久化:利用Scrapy爬取ADHD豆瓣小组的所有帖子的标题、作者、以及最后回复时间,保存在cvs文件中。

数据处理:对每一个标题字符串过滤无意义词汇、分词、关键字提取,Kmeans近义词聚类,统计出现次数最多的10个关键词。

数据可视化:使用Echarts自动生成前十关键词图表。

Scrapy

基本结构

原理图

Scrapy 原理图

这是所有Scrapy教程都会提到一张图,大部分爬虫也是基于这个逻辑,很简洁也很重要,其中:

Pipline是数据管道,一般用来在做数据持久化或其他数据的后续处理

Spiders是编写的爬虫,scrapy支持多爬虫异步运行。

Scheduler维护了一个requests列表,爬虫将按照这个列表发出请求。

Downloader可以从response获取链接并通过迭代使爬虫持续运行。

Middleware可以使数据传输过程中执行一些特殊操作,例如在Downloader Middleware中可以使用selenium执行js代码。

源码

adhdspider.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# -*- coding: utf-8 -*-
import scrapy
import re
import sys

from adhd.items import AdhdItem


class adhdspider(scrapy.Spider):
name = "adhd"
allowed_damains=['https://www.douban.com/group']
start_urls = [
"https://www.douban.com/group/ADD-ADHD/discussion?start=0"
]

def parse(self, response):
item = AdhdItem()
selector = scrapy.Selector(response)

comment = selector.xpath('//*[@id="content"]/div/div[1]/div[2]/table[@class="olt"]')
title = comment.xpath('//tr[*]/td[@class="title"]/a/text()').extract()
author = comment.xpath('//tr[*]/td[@nowrap="nowrap"]/a/text()').extract()
time = comment.xpath('//tr[*]/td[@class="time"]/text()').extract()

#print (len(title))
#print (len(author))
#print (len(time))

for i in range(len(author)):
item['title'] = "".join(title[i].strip())
item['author'] = "".join(author[i].strip())
item['time'] = "".join(time[i].strip())
yield item

try:
next_page = response.xpath('//*[@id="content"]/div/div[1]/div[3]/span[@class="next"]/a/@href').extract()[0]
yield scrapy.Request(next_page)
except:
print("所有信息爬取完毕!")
pass
  1. 这里继承的不是CrawlSpider所以用Request抛出迭代,如果使用CrawlSpider可以通过设置rules和Linkextract来定义迭代规则。
  2. 抛出item是字符串,如果抛出列表会是cvs文件内容异常的丑 :(
  3. chrome复制XPATH要把自渲染的tbody去掉!

piplines.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# -*- coding: utf-8 -*-
import os
import csv

class AdhdPipeline_tocsv(object):
def __init__(self):
catalog = os.path.dirname(__file__) + '/spiders/result.csv'
self.file = open(catalog,'w')
self.write = csv.writer(self.file)

def process_item(self, item, spider):
if item['title']:
self.write.writerow((item['title'],item['author'],item['time']))
return item

def close_spider(self,spider):
self.file.close()

setting.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# -*- coding: utf-8 -*-
BOT_NAME = 'adhd'

SPIDER_MODULES = ['adhd.spiders']
NEWSPIDER_MODULE = 'adhd.spiders'

USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36'

ROBOTSTXT_OBEY = True
FEED_URI = 'file:///home/luty/桌面/result.csv'
FEED_FORMAT = 'CSV'

ITEM_PIPELINES = {
'adhd.pipelines.AdhdPipeline_tocsv': 300,
}

items.py

1
2
3
4
5
6
7
8
# -*- coding: utf-8 -*-
import scrapy

class AdhdItem(scrapy.Item):
title=scrapy.Field()
author=scrapy.Field()
time=scrapy.Field()
pass

run.py

1
2
3
# -*- coding: utf-8 -*-
from scrapy import cmdline
cmdline.execute("scrap crawl adhd".split())

运行结果

运行结果

数据处理

代码

  1. 使用jieba库进行了简单的分词和关键词提取
  2. 设定一个字典dict.txt来设置一些专业名词,例如专注达、择思达等
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# -*- coding: utf-8 -*-
import csv
import re
import jieba
import jieba.analyse
from collections import Counter

jieba.load_userdict('/home/luty/桌面/dict.txt')

with open('/home/luty/桌面/result.csv','r') as csvfile:
reader = csv.reader(csvfile)
column = [row[2] for row in reader]

list=[]
for i in column:
if(i!='title'):
#利用正则库去除标点
temp=re.sub("[\s+\.\!\/_,$%^*(+\"\']+|[+——!,。?、[email protected]#¥%……&*()]+","",i)
result = jieba.analyse.extract_tags(temp, topK=20)
for j in result:
list.append(j)
#print(j)
#print(list)
dic=Counter(list)
for key,vaule in dic.items():
print(key)
print(vaule)

结果

运行结果

数据可视化

等待添加…

参考

Scrapy官方文档

jieba仓库