本篇开始将提及到轻量级大数据架构(Pupil架构,对个人开发者友好)的数据各层次开发与应用实战。环境搭建部分,有兴趣的读者可参考前一部分:轻量大数据架构(1):环境的搭建与配置,从头搭好属于个人的开发环境。
这一篇讲到的是数据采集层部分,数据采集层部分就需要考量到数据源。
对于企业来说,数据源其实有很多种:网站日志或用户行为日志等。
此时一般会使用到Flume/Nifi/Logstash等对自家日志进行大规模采集。——然而对于个人开发者而言,这些软件都要通过配置,所以也非常不友好。
因此此处就只有爬虫可以考虑——爬虫是用于采集外部数据的重要工具,企业里在用它来知晓外界情况,对于个人而言通过爬虫获取数据就更为重要了,因为个人开发者并没有什么内部数据可用。
随后就是爬虫的框架部分:
爬虫的框架分为以下几个部分:
网络IO,此处略过;
爬虫库,主要从Requests,bs4,lxml和Scrapy三个框架来讲,而Tesseract、selenium等框架很多时候容易碰到反爬措施和网站的红线,因此此处略过。
反爬措施的讨论;
爬虫时所涉及的伦理道德与法律法规问题。
爬虫库大概如下:
爬虫库 | 特点 | 用途 | 注意事项 |
requests | 简单易用,能处理大多数问题 | 采集网站数据的第一步 | 需要注意频率和次数,且不支持动态数据 |
beautifulsoup | 树状图 | 解析html数据 | 部分功能需要安装C语言库 |
lxml | 通过xpath定义到元素 | 解析HTML数据 | 遇到混淆需要避让,不支持被编码的数据 |
scrapy | 配置复杂但采取出来的数据非常快速 | 需要获取数据救急 | 需要注意频率和次数,以及诸多配置的问题,不支持动态数据 |
tesseract | 能把字符验证码识别出来 | 测试自己网站的验证码 | 禁止用于获取其他网站的验证码,面对汉语和日语的验证码时需要额外装包 |
selenium | 可以启动浏览器 | 动态加载网页或 | 仅限对自己网站测试,切勿测试其他网站 |
用最轻量的Requests和bs4来获取并解析数据
爬虫的第一个库是requests;该库是请求网页数据的一个库,通常用法是:
import requests
url='a public net'
headers={}
requests.get(url,headers=headers)
这种方式可以通过网站的一些api或接口获得json类型数据,也可以有限度的获取公开网页的数据。然而鉴于很多网站的反爬措施越来越强,因此非常建议添加请求头,常见参数为UA和referer。
但是又需要注意了:在获取数据之前,应优先查看Robots.txt,该协议为君子协议,最好遵守它——上面规定了哪些爬虫不能爬,哪些页面不能爬。
在遵守Robots.txt的情况下,不会有什么事发生;但如果没有遵守,网站可以使用Robot.txt对开发者采取措施,包括封禁ip/账号等,必要时网站可能联合公安机关或司法机关让开发者走法律流程。
然而,requests能提取出干净的json,很多时候提取出来的其实也很可能是不干净的xml,如获取知乎某一页的回答时,或者获取B站弹幕时,其提取出的文件就是一个典型的XML,根据情况来看、
比如以下一段获取B站某视频公开弹幕的时候:
import requests
import re
from bs4 import BeautifulSoup
url="" #省略具体url
headers={}#参数根据个人的ua和referers
response=requests.get(url,headers=headers)
response.encoding='utf-8'
data=response.text
print(data)
如果不加utf-8编码,打出来的是这样:
加了utf-8编码,打出来的是这样:
这个时候会发现它背后其实是一堆xml。如果用Bs4去解析,或者用lxml解析会怎么样,先来看个效果:
soup=BeautifulSoup(data,'html.parser')
print(soup.title)
print(soup.head)
print(soup.d)
用BS4解析时,如果默认html.parser,解析出来的是:
此时我们就需要换成xml解析器:
soup=Beautifulsoup(data,"xml")
获取完成的数据其实就是完整的一条xml记录,不再有爆红。
如果只想获得一段字符串,可以换成:
print(soup.d.string)
这样打出来的就只有“接接接接接”这样的字符串了。
如果想要找到所有的:
d_list = soup.find_all(re.compile("d"))
print(d_list)
for d in d_list:
print(d)
但这样获取的仍然是一个xml结构。此时就该派出re作为救星了。
data=re.findall('<d p=".*?">(.*?)</d>',data)
for d in data:
print(d)
虽然bs4在解析网站的时候很有效,但是遇到这种很复杂的情况就不能再用bs4了,回到re的最轻量化才是最重要的。
bs4其实还有以下的用法:
find_all(name, attrs, recursive, text, **kwargs)
soup.select('')#按类名查找,支持HTML与css
但里面的细节相对较多,暂时不予赘述。
LXML和BS4的异同——解析数据时需要重点考虑的地方
lxml和bs4一样都支持解析xml,但是二者所解析方式有所不同。
LXML通过etree来解析数据,可以支持xpath和xslt处理;但一般采取的都是xpath;也适合在部分场景下把xml和json互相转换。
比如:
data_2=response.text
tree=etree.XML(data_2)
danmaku=tree.xpath('//d/')
但这样做也有个缺点:不允许任何被编码的数据解析出来。
对于需要编码的数据,用re库比xml来处理更合适。
Scrapy——如何快速的获取数据救急?
Scrapy是一种很轻快的爬虫框架,能够获得很干净的数据,支持item/pipeline/spider等原生类;还有splash和scrapy-Redis作为扩展。
但这里也不推荐使用scrapy,仅限特殊情况使用,此处也不赘述;scrapy的缺点其实很明显:一是框架味觉超重,scrapy自带「管道+中间件」全套香料架,抓轻量数据时像用冬阴功汤底煮泡面,框架开销比数据量还大(香料比面多);二是异步味觉迟钝:虽用Twisted异步,但轻量场景下并发优势为0,像用香茅叶扇风降温,不如直接吹电扇(requests单线程更高效);三是操作过于复杂,一套pipeline配置完要数小时或者数十分钟。
Tesseract/Selenium——采集网络大数据的“双刃剑”
Tesseract对于字母验证码其实是很好用的,但面对汉语/日语这样的涉及汉字的语言进行验证码识别就需要额外加包。并且Tesseract环节还需要涉及验证码下载,步骤较为冗长,故不推荐使用,此处不予赘述。除此之外,很多第三方的api也支持验证码识别,但本文不建议任何个人开发者这么做。
Selenium适合采集需要动态加载的数据,一般适用于自动化测试。
由于selenium采集的平台一般都比较复杂,对于个人开发者并不友好,所以也不在此赘述。
网站的反爬措施和简单的应对方法
网站的反爬措施如下:
反爬措施 | 影响 | 应对方案 | 推荐程度(10为满分) |
JS逆向与混淆 | 需要用户登录的场面进不去,无法通过selenium访问 | 绕过selenium走官方api | 10 |
IP封锁 | 一段时间内无法采集到数据 | 必要时才考虑随机代理池,一般情况下采用限速与限量,随机间隔等方式 | 9 |
通过请求头 | 无头爬虫直接被拦 | 使用headers传递参数,保留ua和referer | 10 |
验证码 | 需要用户登录的场面进不去 | 放弃验证码,走官方API | 10 |
动态cookies | 用静态方式访问会直接403 | 使用selenium | 5(使用selenium存在风险) |
通过JS动态加载 | 直接获得的数据不完整 | 使用selenium | 5 |
一旦遇到反爬措施,通常意味着在采集网络数据时即将踩到网站红线。此时对于个人开发者而言,就不应继续通过网页获取数据了,而是换个方式,要么通过API接口,要么通过与平台合作的方式进行数据获取,否则承担的法律后果和法律责任可不是一般开发者所能承受。
以下是一些api的获取方式:
在b站对页面右击,点击检查;
点击检查后刷新页面,搜索评论,会弹出对应接口——藏在main当中。其他可以使用的接口还包括view。
运用该类api时,需要严格保管好自己的相应key,并限量限速(推荐12-30秒的随机间隔)。
除此之外还有view类,可以查看对应视频的播放和弹幕数量,且比网页解析更精准。
弹幕的话通过https://ibilibili.com/video/bvid这样的格式获得对应的api。
其他的api还包括飞瓜,美团等的api,但大多数需要开公司,成本并不低;淘宝的api可以根据用量付费;抖音可以通过开放平台创建应用,每一个应用都有key。
在运用这些API或者网页解析时需要考虑到伦理道德与法律法规,放在下一部分提及。
在进行数据采集时需要注意的伦理道德和法律法规
数据采集层主要以网络爬虫为主,所以涉及到的伦理道德问题和法律法规问题其实都不少。
获取数据时,字段禁止采集任何包含uname/id相关的字段,泛泛而谈即任何可能关联到他人敏感信息的如uname/id/address/ip之类的都不允许采集。
数据获取后,需要检查获取的内容是否有任意可能的特定名词关联信息,若有则必须处理掉:
import pandas as pd
data=pd.read_csv("")
df=pd.DataFrame(data)
df['comment']=df['comment'].str.replace(r'群聊|链接|加V|私信|others','')#此处others是包括要过滤的任何敏感或违规内容
反例:
2021年9月,江苏省无锡市梁溪区人民法院审结了一起提供侵入计算机信息系统程序罪案件,被告人丁某因向他人售卖非法获取某短视频平台用户数据的“爬虫”软件,被判处有期徒刑1年6个月,缓刑2年。据悉,该案系全国首例短视频平台领域网络“爬虫”案件。参考案例1——全国首例!这个案子,判了
获取的数据仅允许供个人学习或研究使用,禁止商用;采集数据时禁止突破网站的反爬措施甚至使用其它工具。
反例1:2024年11月,四川省成都市双流区人民法院审结了一起利用“爬虫”软件非法抓取电商数据的案件,以非法控制计算机信息系统罪判处二被告人有期徒刑六个月至八个月不等,并处罚金,依法没收作案工具。参考案例2——利用“爬虫”技术非法抓取电商数据 两被告人均获刑
反例2:参考案例3——“爬虫”变“害虫”!非法爬取“小红书”数据牟利650余万元,3人被判刑
这也就是轻量大数据架构采集层所涉及的大体内容了,存储层的问题将放到下期分解。