基于Scrapy的微博爬虫设计
2018-02-28张安启罗批
张安启 罗批
摘要 新浪微博是数据的重要发源地。为实现数据快速抓取,本文在研究反爬机制的基础上,设计了基于Scrapy的微博爬虫,并对各模块进行了详细阐述。实验表明,该爬虫具有支持关键字匹配、速度快、简单的特点。为研究者提供了快速、准确、方便地获取微博数据的途径。
【关键词】Scrapy 爬虫 微博
微博自诞生之日起就获得迅猛发展。截至2017年9月,新浪微博的活跃用户高达3.76亿,较之去年同期增长27%。微博作为网民交流互动的平台,时刻产生着大量的数据,对于研究具有重要意义。当前通过微博开放接口(API)获取数据存在诸多的限制,而且流程复杂、速度较慢。
Sctapy是为爬取网络结构性数据而编写的应用框架,具有简单、模块清晰的特点。Scrapy框架对于设计爬取新浪微博数据的爬虫具有十分重要的意义。本文研究了当前微博的反爬机制,并对该机制制定了相应的策略。并依此設计了基于Scrapy的微博爬虫。并通过实验验证了设计的爬虫的有效性。
1 当前的反爬虫机制
当前的反爬机制主要有以下四种:
(1) IP地址的限制。微博服务器对登录网站的IP地址进行监测,如果某一个IP地址访问频率过高或者持续时间过久,就会判定使用该IP的用户为爬虫并对该IP进行封锁。令其无法访问微博或者通过验证后方可进行访问。
(2)浏览器的限制。浏览器的标识存在于headers属性当中。如果检测到某一个浏览器频繁地访问,便会封杀该浏览器。
(3)对账号的限制。因为一个人不可能频繁大量长时间地访问微博,因此如果某一账号频繁不间断的访问微博,该账号就需要重新验证方可继续访问。
(4)对访问频率的限制。由于爬虫浏览速率非常快,高于普通人浏览网页的几十倍甚至上百倍。因此,如果访问频率过高,也会将其判定为爬虫,对其要求进行验证。
由此可见,当前的反爬机制主要是通过对正常网民行为进行识别。当某个网民的行为与正常网民的行为不一致的时候,就会判定该网民为爬虫。因此,为了应对反爬虫机制,就应该让爬虫行为与正常用户行为更为相似。
2 应对反爬虫的策略
针对微博的反爬虫策略,在此制定防止反爬虫的设计。
(1)建立由多个IP地址组成的IP池。每进行一次新的页面访问,从IP池中随机抽取一个IP地址。这样可以避免某个IP地址被封杀。
(2)建立多个移动浏览器标识的客户端类型池。由于当前人们习惯于使用手机等移动设备上网,因而使用移动设备浏览器登录网站理论上讲是个较为安全的方式。从移动客户端类型池中每次随机抽取一个客户端,模拟网民登陆。
(3)建立多个账号组成的账号池。每次访问新的页面,从账号池中随机抽取一个账号,有效降低单个账号的访问频率。
(4)增大访问时延。通过增大访问时延,降低访问频率,模拟正常人的访问,实现对反爬虫机制的回避。
3 基于Scrapy的爬虫工作原理
图1是Scrapy框架图,现在对其各个模块以及运行流程进行介绍。
3.1 模块介绍
引擎( Scrapy Engine):它是整个框架的核心,数据在各个模块的流动都需要通过引擎的牵引来实现。
调度器(Schedule)接受引擎模块发来的request,并将request压入队列。在进行微博抓取的时候主要是URL队列。调度器对URL队列进行处理,主要是排序与去重。
下载器(Downloader):从互联网上获取数据,并将内容反馈给爬虫( Spiders)模块。
管道(Pipelines):处理从网页中抽取的实体(Items),主要功能是验证实体有效性和清除无意义的信息。页面被解析后,将会被发送到管道中进行处理。本实验结合Mongodb数据库,通过Pipelines将数据直接导入Mongodb数据库中。
中间件(Middlewares):处理两个模块之间的信息请求以及进行相应。
3.2 运行流程
引擎将调度器里的URL封装成请求( Requests),传送到下载器,下载器从互联网上将数据下载下来,将其封装成应答包( Responses)并传送给爬虫。爬虫对应答包进行解析得到实体或URL。如果是实体,则交给管道进行进一步处理。如果是URL,则将结果交给调度器处理。
4 爬虫的各个模块设计
4.1 Cookies模块
Cookies模块主要用于在一定时间内,记录登录数据,在进行登录的时候可以保持登录的状态。在本文设计的cookies模块中,记录的是多个用户账号组成的账号池,用来登陆微博网站时先切换账号。主要伪代码如下:
weib0 =[{num‘:‘1 5022967940,psw:OC3LKP'),……]#建立微博账号池,账号池中的账号越多,被封杀的可能性越低,时延可以设置越低,爬取速度越快
def getCookies(、veibo):#获取Cookies
cookies =[]
loginURL= 'https:,//weibo.cn/login/'#微博网站登陆界面
for elem in weibo:#从微博账号池中抽取一个账号进行登录
account= elem[num]
password = elem[psw‘]
try:
browser= webdriver.PhantomjS(desiredcapabilities=dcap) browser.get(loginURL)
if出现需要识别的代码
人工识别代码并在界面上输入代码
4.2 Items模块
该模块主要明确抓取数据的类型。本文抓取的实验数据类型是用户的用户名,用户粉丝数、微博内容、发布时间、转发数、点赞数以及评论数三个指标。其主要代码为:
from scrapy import Item, Field
class Informationltem(ltem):#个人信息
id= Field()#用户ID
Fans= Field()#用户粉丝
Content= Field()#微博内容
PubTime= Field()#发表时间
Transfer= Field()#转发数
Like= Field()#点赞数
Comment= Field()#评论数
4.3 Middlewares模塊
该模块主要实现浏览器、IP地址以及登陆账号(登陆账号在cookies中)的转换,防止被禁止爬取数据。其主要代码如下:
import random
import urlllib.request
from cookies import cookies
agents=["Mozilla/5.0 (Linux; U;Android 2.3.6; en-us; Nexus S Build/GRK39F)AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 Mobile Safari/533.1”,—…]#建立移动浏览器池
ips= [23.25.35.66,….]#建立ip地址池
class UserAgentIPMiddleware(object): #更换User-Agent与IP
def process_request(self, request, spider):
agent= random.choice(agents)#从移动浏览器池中随机抽取一个移动浏览器
ip= random.choice(ips)#从IP池中随机抽取IP
request.headers["User-Agent"]= agenr##访问网站的浏览器头设置为抽取的移动浏览器
ip_support=urllib.requestProxyHandler({ thttp':ip})
opener= urllib.request.build_opener(ipsupport)
urllib.request.install_opener(opener)
class CookiesMiddleware(object):#更 换Cookie
def process_request(self, request, spider):
cookie= random.choice(cookies)#从cookies池中随机抽取cookie
request.cookies= cookie
4.4 Pipelines模块
该模块主要对抓取的数据进行解析校对,然后传入Mongodb数据库中。其主要代码如下:
import pymongo
fromltems import Informationltem
class MongoDBPipleline(object):#初始化设置MongoDB数据库
defjnit_(selt):
clinet= pymongo.MongoClient("localhost",27017)
db = clinet["Sina"]
selflnformation= db["Information"]
def processjtem(selt item, spider):#判断item的类型,并作相应的处理,再入数据库
ifisinstance(item, Informationltem):
try:
self.lnformation.insert(dict(item》
except Exception:
pass
retumltem
4.5 Settings模块
该模块主要设置抓取的间隔时间与关键词等信息。在这设置抓取间隔为6,关键词为租赁房。主要代码如下:
DOWNLOAD__ DELAY=6井间隔时间
KEY WORD=‘租赁房#关键词
4.6 Spider主程序(引擎模块)
该模块是整个程序的核心,通过该模块实现数据的抓取。主要代码如下:
def start_requests(self):#依据关键词获取微博,并将该微博的用户的地址url
url={url} ?keyword= {keyword}format(url=self.search_url, keyword=KEYWORD)
# search url为微博搜索界面
defparse (self, response):#抓取微博数据
selector= Selector(response)
rweets=selector.xpath(body/div[@class='c”and@idD
for tweet in tweets:
nveetsltems= Tweetsltem()
id= tweet.xpath(@id').extract_first()#獲取微博ID
fans= response.xpath(”//div[@class=tip2]/a[contains(text(),‘粉丝[)]/text()”)#获取粉丝
content= tweet.xpath(‘div/span[@class=”ctt”]/text()).extract_first()#获取微博内容
like= re.findall(u\u8d5e\[(\d+)、],tweet.extract(》#获取点赞数
transfer= re.findall(u‘\u8f6c\u53d1、[(\d_)m tweet.extracr(》#获取转载数
comment= re.findall(u‘\u8bc4\u8bba、[(\d+)m tweet.extract(》#获取评论数5实验运行平台
实验平台:联想E431电脑
具体配置:CPU intel i5-4320、8G内存、2G显卡、256G固态硬盘
6 实验分析
本实验以群众最为关心的租赁房作为关键词进行数据的抓取,在爬虫运行的86小时23分钟内,共计爬取了9910个用户的18633554条数据。
图2是爬取的部分数据截图:从左到右为用户名、粉丝数、微博内容、转发数、点赞数、评论数及发布时间。
依据粉丝数多少绘制用户的累计分布概率进行绘制,得到的结果如图3所示。
这说明关于“租赁房”这一社会热点话题的参与者的粉丝呈幂率分布,关心该话题的大部分人为拥有少量粉丝的普通民众。这也与当前社会现实相一致,拥有大量粉丝的网络大V占据极少数,绝大多数的网民只拥有极少数的粉丝。
7 总结
通过分析当前的反爬机制,运用Scrapy框架简单、模块清晰的特点以及python丰富完善的标准库,设计了基于Scrapy的网络爬虫。通过实验证实,该爬虫能够实现对数据的高效爬取,为科研工作者获取微博数据提供了一个较为简单快捷的工具。在搜索时,只需要将关键词修改,就可实现该主题数据的爬取。
参考文献
[1]新浪微博数据中心:2 017微博用户发展报告[EB/OL] http://www. useit. com. cn/thread-17562-1-1.html, 2017.
[2]郭涛,黄铭钧,社区网络爬虫的设计与实现[J],智能计算机与应用,2012,2 (04):65-67.
[3]廉捷,周欣,曹伟等.新浪微博数据挖掘方案[J].清华大学学报:自然科学版,2011, 51(10):1300-1305.
[4]赵本本,殷旭东,王伟.基于Scrapy的GitHub数据爬虫[J],电子技术与软件工程,2016,6:199-202.
[5]陈利婷,大数据时代的反爬虫技术[J].电脑与信息技术,2016,24 (06): 60-61.
[6]安子建.基于Scrapy框架的网络爬虫实现与数据抓取分析[D].长春:吉林大学,2016.
[7]陈琳,任芳,基于Python的新浪微博数据爬虫程序设计[J].信息系统工程,2016 (09):97-99.