‘壹’ 如何用python写一个分布式爬虫
本文将会以PC端微博进行讲解,因为移动端微博数据不如PC短全面,而且抓取和解析难度都会小一些。文章比较长,由于篇幅所限,文章并没有列出所有代码,只是讲了大致流程和思路。
要抓微博数据,第一步便是模拟登陆,因为很多信息(比如用户信息,用户主页微博数据翻页等各种翻页)都需要在登录状态下才能查看。关于模拟登陆进阶,我写过两篇文章,一篇是模拟登陆微博的,是从小白的角度写的。另外一篇是模拟登陆网络云的,是从有一定经验的熟手的角度写的。读了这两篇文章,并且根据我写的过程自己动手实现过的同学,应该对于模拟登陆PC端微博是没有太大难度的。那两篇文章没有讲如何处理验证码,这里我简单说一下,做爬虫的同学不要老想着用什么机器学习的方法去识别复杂验证码,真的难度非常大,这应该也不是一个爬虫工程师的工作重点,当然这只是我的个人建议。工程化的项目,我还是建议大家通过打码平台来解决验证码的问题。我在分布式微博爬虫中就是直接调用打码平台的接口来做的大规模微博账号的模拟登陆,效果还不错,而且打码成本很低。
说完模拟登陆(具体请参见我写的那两篇文章,篇幅所限,我就不过来了),我们现在正式进入微博的数据抓取。这里我会以微博用户信息抓取为例来进行分析和讲解。
关于用户信息抓取,可能我们有两个目的。一个是我们只想抓一些指定用户,另外一个是我们想尽可能多的抓取更多数量的用户的信息。我的目的假定是第二种。那么我们该以什么样的策略来抓取,才能获得尽可能多的用户信息呢?如果我们初始用户选择有误,选了一些不活跃的用户,很可能会形成一个环,这样就抓不了太多的数据。这里有一个很简单的思路:我们把一些大V拿来做为种子用户,我们先抓他们的个人信息,然后再抓大V所关注的用户和粉丝,大V关注的用户肯定也是类似大V的用户,这样的话,就不容易形成环了。
策略我们都清楚了。就该是分析和编码了。
我们先来分析如何构造用户信息的URL。这里我以微博名为一起神吐槽的博主为例进行分析。做爬虫的话,一个很重要的意识就是爬虫能抓的数据都是人能看到的数据,反过来,人能在浏览器上看到的数据,爬虫几乎都能抓。这里用的是几乎,因为有的数据抓取难度特别。我们首先需要以正常人的流程看看怎么获取到用户的信息。我们先进入该博主的主页,如下图
根据唯一性判断
我们在页面源码中搜索,只发现一个script中有该字符串,那么就是那段script是页面相关信息。我们可以通过正则表达式把该script提取出来,然后把其中的html也提取出来,再保存到本地,看看信息是否全面。这里我就不截图了。感觉还有很多要写的,不然篇幅太长了。
另外,对于具体页面的解析,我也不做太多的介绍了。太细的东西还是建议读读源码。我只讲一下,我觉得的一种处理异常的比较优雅的方式。微博爬虫的话,主要是页面样式太多,如果你打算包含所有不同的用户的模版,那么我觉得几乎不可能,不同用户模版,用到的解析规则就不一样。那么出现解析异常如何处理?尤其是你没有catch到的异常。很可能因为这个问题,程序就崩掉。其实对于Python这门语言来说,我们可以通过装饰器来捕捉我们没有考虑到的异常,比如我这个装饰器
Python
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
def parse_decorator(return_type):
"""
:param return_type: 用于捕捉页面解析的异常, 0表示返回数字0, 1表示返回空字符串, 2表示返回[],3表示返回False, 4表示返回{}, 5返回None
:return: 0,'',[],False,{},None
"""
def page_parse(func):
@wraps(func)
def handle_error(*keys):
try:
return func(*keys)
except Exception as e:
parser.error(e)
if return_type == 5:
return None
elif return_type == 4:
return {}
elif return_type == 3:
return False
elif return_type == 2:
return []
elif return_type == 1:
return ''
else:
return 0
return handle_error
return page_parse
上面的代码就是处理解析页面发生异常的情况,我们只能在数据的准确性、全面性和程序的健壮性之间做一些取舍。用装饰器的话,程序中不用写太多的try语句,代码重复率也会减少很多。
页面的解析由于篇幅所限,我就讲到这里了。没有涉及太具体的解析,其中一个还有一个比较难的点,就是数据的全面性,读者可以去多观察几个微博用户的个人信息,就会发现有的个人信息,有的用户有填写,有的并没有。解析的时候要考虑完的话,建议从自己的微博的个人信息入手,看到底有哪些可以填。这样可以保证几乎不会漏掉一些重要的信息。
最后,我再切合本文的标题,讲如何搭建一个分布式的微博爬虫。开发过程中,我们可以先就做单机单线程的爬虫,然后再改成使用celery的方式。这里这样做是为了方便开发和测试,因为你单机搭起来并且跑得通了,那么分布式的话,就很容易改了,因为celery的API使用本来就很简洁。
我们抓取的是用户信息和他的关注和粉丝uid。用户信息的话,我们一个请求大概能抓取一个用户的信息,而粉丝和关注我们一个请求可以抓取18个左右(因为这个抓的是列表),显然可以发现用户信息应该多占一些请求的资源。这时候就该介绍理论篇没有介绍的关于celery的一个高级特性了,它叫做任务路由。直白点说,它可以规定哪个分布式节点能做哪些任务,不能做哪些任务。它的存在可以让资源分配更加合理,分布式微博爬虫项目初期,就没有使用任务路由,然后抓了十多万条关注和分析,结果发现用户信息抓几万条,这就是资源分配得不合理。那么如何进行任务路由呢?
Python
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
# coding:utf-8
import os
from datetime import timedelta
from celery import Celery
from kombu import Exchange, Queue
from config.conf import get_broker_or_backend
from celery import platforms
# 允许celery以root身份启动
platforms.C_FORCE_ROOT = True
worker_log_path = os.path.join(os.path.dirname(os.path.dirname(__file__))+'/logs', 'celery.log')
beat_log_path = os.path.join(os.path.dirname(os.path.dirname(__file__))+'/logs', 'beat.log')
tasks = ['tasks.login', 'tasks.user']
# include的作用就是注册服务化函数
app = Celery('weibo_task', include=tasks, broker=get_broker_or_backend(1), backend=get_broker_or_backend(2))
app.conf.update(
CELERY_TIMEZONE='Asia/Shanghai',
CELERY_ENABLE_UTC=True,
CELERYD_LOG_FILE=worker_log_path,
CELERYBEAT_LOG_FILE=beat_log_path,
CELERY_ACCEPT_CONTENT=['json'],
CELERY_TASK_SERIALIZER='json',
CELERY_RESULT_SERIALIZER='json',
CELERY_QUEUES=(
Queue('login_queue', exchange=Exchange('login', type='direct'), routing_key='for_login'),
Queue('user_crawler', exchange=Exchange('user_info', type='direct'), routing_key='for_user_info'),
Queue('fans_followers', exchange=Exchange('fans_followers', type='direct'), routing_key='for_fans_followers'),
)
上述代码我指定了有login_queue、user_crawler、fans_followers三个任务队列。它们分别的作用是登录、用户信息抓取、粉丝和关注抓取。现在假设我有三台爬虫服务器A、B和C。我想让我所有的账号登录任务分散到三台服务器、让用户抓取在A和B上执行,让粉丝和关注抓取在C上执行,那么启动A、B、C三个服务器的celery worker的命令就分别是
Python
1
2
3
celery -A tasks.workers -Q login_queue,user_crawler worker -l info -c 1 # A服务器和B服务器启动worker的命令,它们只会执行登录和用户信息抓取任务
celery -A tasks.workers -Q login_queue,fans_followers worker -l info -c 1 # C服务器启动worker的命令,它只会执行登录、粉丝和关注抓取任务
然后我们通过命令行或者代码(如下)就能发送所有任务给各个节点执行了
Python
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
41
4
‘贰’ 用python写一个爬虫有多难
爬虫是互联网上最常见的一种东西了吧。
爬虫这东西每天都在网上爬大量的信息,各大搜索引擎厂商每天都有上百万的爬虫在网络上活动,这些爬虫的作用就是给搜索引擎采集互联网上最新的内容,采集来的内容经过分类、加工之后,进入搜索引擎的索引。这是爬虫最常见的应用。
关于搜索引擎的理论非常多,应该已经形成系统的理论和方法了。这里不再多追求搜索引擎的细节,只来看看爬虫如何爬有效的信息。
ps. 这个博客已经很久没有更新了。现在时间越来越少,平时鲜有时间来更新博客了。
最近某人发现,python其实是一种很适合写爬虫的语言,而且python越用越顺手。现在若是有人问我“c++和c#学哪一个?“之类的问题的时候,我一定会说,学python吧,因为生命短暂,你应该学习python。
所谓爬虫,就是把网页的html下载下来,然后从里面提取出来有用的信息,这些有用的信息一般就是正文,图片,链接一类的信息。
针对特定网站的爬虫就更好写了,用正则表达式,把网页里的链接信息找到,然后找到需要的信息,保存在本地,然后进入下一个链接重复上一次的过程。
下面的脚本演示如何从加菲猫的官网上把从1978年至今的所有漫画全部下载下来
import os,urllib,urllib2,re
hosts = "http://**********"
#initpos = "/mobile/garfield/1978/06/19"
initpos ="/mobile/garfield/1979/08/08"
pname = re.compile('''<span class="authorText">.+?<em>(.*?)</em></span>''')
pcomic = re.compile('''<div id="comic".+?src="(.*?)".+?</div>''')
pnext = re.compile('''<a href="(.*?)" class="next">''')
def getpage(url):
print url
req = urllib2.Request(url)
req.add_header("User-Agent","Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:21.0) Gecko/20100101 Firefox/21.0")
req.add_header("If-None-Match","")
u = urllib2.urlopen(req).read()
return u
def getnextpos(content,patten):
r = patten.findall(content)
for x in r:
print 'find next: ',x
return x
def savecomic(content,patten):
r = patten.findall(content)
print 'find commic:',r
r2 = pname.findall(content)
print 'find name:',r2
urlcomic = r[0]
u = urllib.urlopen(urlcomic).read()
name = r2[0].replace(' ','').split(',')
year = name[-1]
day = name[-2]
filename = 'test.jpg'
if not os.path.exists(year):
os.makedirs(year)
# is gif file ,the name the file as gif
if ((u[0] is 'G') and (u[1] is 'I') and (u[2] is 'F')):
filename = year+day+'.gif'
else:
filename = year+day+'.jpg'
f = file(year+"/"+filename,"wb+")
f.write(u)
f.close()
def main():
url = hosts+initpos
while(True):
c = getpage(url)
savecomic(c,pcomic)
u = getnextpos(c,pnext)
if u is None:
break
else:
url = hosts+u
if __name__ == '__main__':
main()
‘叁’ Python语言的爬虫好写吗
不难的,python3自带的urllib模块可以编写轻量级的简单爬虫。至于怎么定位一个网页中具体元素的url可自行网络火狐浏览器的firebug插件或者谷歌浏览器的自带方法
欢迎您关注我,遇到问题可以与我交流沟通
‘肆’ 如何用python写出爬虫
先检查是否有API
API是网站官方提供的数据接口,如果通过调用API采集数据,则相当于在网站允许的范围内采集,这样既不会有道德法律风险,也没有网站故意设置的障碍;不过调用API接口的访问则处于网站的控制中,网站可以用来收费,可以用来限制访问上限等。整体来看,如果数据采集的需求并不是很独特,那么有API则应优先采用调用API的方式。
数据结构分析和数据存储
爬虫需求要十分清晰,具体表现为需要哪些字段,这些字段可以是网页上现有的,也可以是根据网页上现有的字段进一步计算的,这些字段如何构建表,多张表如何连接等。值得一提的是,确定字段环节,不要只看少量的网页,因为单个网页可以缺少别的同类网页的字段,这既有可能是由于网站的问题,也可能是用户行为的差异,只有多观察一些网页才能综合抽象出具有普适性的关键字段——这并不是几分钟看几个网页就可以决定的简单事情,如果遇上了那种臃肿、混乱的网站,可能坑非常多。
对于大规模爬虫,除了本身要采集的数据外,其他重要的中间数据(比如页面Id或者url)也建议存储下来,这样可以不必每次重新爬取id。
数据库并没有固定的选择,本质仍是将Python里的数据写到库里,可以选择关系型数据库MySQL等,也可以选择非关系型数据库MongoDB等;对于普通的结构化数据一般存在关系型数据库即可。sqlalchemy是一个成熟好用的数据库连接框架,其引擎可与Pandas配套使用,把数据处理和数据存储连接起来,一气呵成。
数据流分析
对于要批量爬取的网页,往上一层,看它的入口在哪里;这个是根据采集范围来确定入口,比如若只想爬一个地区的数据,那从该地区的主页切入即可;但若想爬全国数据,则应更往上一层,从全国的入口切入。一般的网站网页都以树状结构为主,找到切入点作为根节点一层层往里进入即可。
值得注意的一点是,一般网站都不会直接把全量的数据做成列表给你一页页往下翻直到遍历完数据,比如链家上面很清楚地写着有24587套二手房,但是它只给100页,每页30个,如果直接这么切入只能访问3000个,远远低于真实数据量;因此先切片,再整合的数据思维可以获得更大的数据量。显然100页是系统设定,只要超过300个就只显示100页,因此可以通过其他的筛选条件不断细分,只到筛选结果小于等于300页就表示该条件下没有缺漏;最后把各种条件下的筛选结果集合在一起,就能够尽可能地还原真实数据量。
明确了大规模爬虫的数据流动机制,下一步就是针对单个网页进行解析,然后把这个模式复制到整体。对于单个网页,采用抓包工具可以查看它的请求方式,是get还是post,有没有提交表单,欲采集的数据是写入源代码里还是通过AJAX调用JSON数据。
同样的道理,不能只看一个页面,要观察多个页面,因为批量爬虫要弄清这些大量页面url以及参数的规律,以便可以自动构造;有的网站的url以及关键参数是加密的,这样就悲剧了,不能靠着明显的逻辑直接构造,这种情况下要批量爬虫,要么找到它加密的js代码,在爬虫代码上加入从明文到密码的加密过程;要么采用下文所述的模拟浏览器的方式。
数据采集
之前用R做爬虫,不要笑,R的确可以做爬虫工作;但在爬虫方面,Python显然优势更明显,受众更广,这得益于其成熟的爬虫框架,以及其他的在计算机系统上更好的性能。scrapy是一个成熟的爬虫框架,直接往里套用就好,比较适合新手学习;requests是一个比原生的urllib包更简洁强大的包,适合作定制化的爬虫功能。requests主要提供一个基本访问功能,把网页的源代码给download下来。一般而言,只要加上跟浏览器同样的Requests Headers参数,就可以正常访问,status_code为200,并成功得到网页源代码;但是也有某些反爬虫较为严格的网站,这么直接访问会被禁止;或者说status为200也不会返回正常的网页源码,而是要求写验证码的js脚本等。
下载到了源码之后,如果数据就在源码中,这种情况是最简单的,这就表示已经成功获取到了数据,剩下的无非就是数据提取、清洗、入库。但若网页上有,然而源代码里没有的,就表示数据写在其他地方,一般而言是通过AJAX异步加载JSON数据,从XHR中找即可找到;如果这样还找不到,那就需要去解析js脚本了。
解析工具
源码下载后,就是解析数据了,常用的有两种方法,一种是用BeautifulSoup对树状HTML进行解析,另一种是通过正则表达式从文本中抽取数据。
BeautifulSoup比较简单,支持Xpath和CSSSelector两种途径,而且像Chrome这类浏览器一般都已经把各个结点的Xpath或者CSSSelector标记好了,直接复制即可。以CSSSelector为例,可以选择tag、id、class等多种方式进行定位选择,如果有id建议选id,因为根据HTML语法,一个id只能绑定一个标签。
正则表达式很强大,但构造起来有点复杂,需要专门去学习。因为下载下来的源码格式就是字符串,所以正则表达式可以大显身手,而且处理速度很快。
对于HTML结构固定,即同样的字段处tag、id和class名称都相同,采用BeautifulSoup解析是一种简单高效的方案,但有的网站混乱,同样的数据在不同页面间HTML结构不同,这种情况下BeautifulSoup就不太好使;如果数据本身格式固定,则用正则表达式更方便。比如以下的例子,这两个都是深圳地区某个地方的经度,但一个页面的class是long,一个页面的class是longitude,根据class来选择就没办法同时满足2个,但只要注意到深圳地区的经度都是介于113到114之间的浮点数,就可以通过正则表达式"11[3-4].\d+"来使两个都满足。
数据整理
一般而言,爬下来的原始数据都不是清洁的,所以在入库前要先整理;由于大部分都是字符串,所以主要也就是字符串的处理方式了。
字符串自带的方法可以满足大部分简单的处理需求,比如strip可以去掉首尾不需要的字符或者换行符等,replace可以将指定部分替换成需要的部分,split可以在指定部分分割然后截取一部分。
如果字符串处理的需求太复杂以致常规的字符串处理方法不好解决,那就要请出正则表达式这个大杀器。
Pandas是Python中常用的数据处理模块,虽然作为一个从R转过来的人一直觉得这个模仿R的包实在是太难用了。Pandas不仅可以进行向量化处理、筛选、分组、计算,还能够整合成DataFrame,将采集的数据整合成一张表,呈现最终的存储效果。
写入数据库
如果只是中小规模的爬虫,可以把最后的爬虫结果汇合成一张表,最后导出成一张表格以便后续使用;但对于表数量多、单张表容量大的大规模爬虫,再导出成一堆零散的表就不合适了,肯定还是要放在数据库中,既方便存储,也方便进一步整理。
写入数据库有两种方法,一种是通过Pandas的DataFrame自带的to_sql方法,好处是自动建表,对于对表结构没有严格要求的情况下可以采用这种方式,不过值得一提的是,如果是多行的DataFrame可以直接插入不加索引,但若只有一行就要加索引否则报错,虽然这个认为不太合理;另一种是利用数据库引擎来执行SQL语句,这种情况下要先自己建表,虽然多了一步,但是表结构完全是自己控制之下。Pandas与SQL都可以用来建表、整理数据,结合起来使用效率更高。
‘伍’ Python爬虫好写吗
python爬虫不简单的,基础爬虫:
(1)基础库:urllib模块/requests第三方模块
首先爬虫就是要从网页上把我们需要的信息抓取下来的,那么我们就要学习urllib/requests模块,这两种模块是负责爬取网页的。这里大家觉得哪一种用的习惯就用哪一种,选择一种精通就好了。我推荐读者使用使用requests模块,因为这一种简便很多,容易操作、容易理解,所以requests被称为“人性化模块”。
(2)多进程、多线程、协程和分布式进程:
为什么要学着四个知识呢?假如你要爬取200万条的数据,使用一般的单进程或者单线程的话,你爬取下载这些数据,也许要一个星期或是更久。试问这是你想要看到的结果吗?显然单进程和单线程不要满足我们追求的高效率,太浪费时间了。只要设置好多进程和多线程,爬取数据的速度可以提高10倍甚至更高的效率。
(3)网页解析提取库:xpath/BeautifulSoup4/正则表达式
通过前面的(1)和(2)爬取下来的是网页源代码,这里有很多并不是我们想要的信息,所以需要将没用的信息过滤掉,留下对我们有价值的信息。这里有三种解析器,三种在不同的场景各有特色也各有不足,总的来说,学会这三种灵活运用会很方便的。推荐理解能力不是很强的朋友或是刚入门爬虫的朋友,学习BeautifulSoup4是很容易掌握并能够快速应用实战的,功能也非常强大。
(4)反屏蔽:请求头/代理服务器/cookie
在爬取网页的时候有时会失败,因为别人网站设置了反爬虫措施了,这个时候就需要我们去伪装自己的行为,让对方网站察觉不到我们就是爬虫方。请求头设置,主要是模拟成浏览器的行为;IP被屏蔽了,就需要使用代理服务器来破解;而cookie是模拟成登录的行为进入网站。
(5)异常:超时处理/异常处理,这里不做介绍了,自己去了解一下。
(6)数据储存库:文件系统储存/MySQL/MongoDB
数据的储存大概就这三种方式了,文件系统储存是运用了python文件操作来执行的;而MySQL要使用到数据库创建表格来储存数据;MongoDB在爬虫里是非常好的储存方式,分布式爬虫就是运用了MongoDB来储存的。各有特色,看自己需要哪种,在灵活运用。
(7)动态网页抓取:Ajax/PhantomJS/Selenium这三个知识点
(8)抓包:APP抓包/API爬虫
(9)模拟登陆的 爬虫
‘陆’ Python爬虫如何写
先检查是否有API
API是网站官方提供的数据接口,如果通过调用API采集数据,则相当于在网站允许的范围内采集,这样既不会有道德法律风险,也没有网站故意设置的障碍;不过调用API接口的访问则处于网站的控制中,网站可以用来收费,可以用来限制访问上限等。整体来看,如果数据采集的需求并不是很独特,那么有API则应优先采用调用API的方式。
数据结构分析和数据存储
爬虫需求要十分清晰,具体表现为需要哪些字段,这些字段可以是网页上现有的,也可以是根据网页上现有的字段进一步计算的,这些字段如何构建表,多张表如何连接等。值得一提的是,确定字段环节,不要只看少量的网页,因为单个网页可以缺少别的同类网页的字段,这既有可能是由于网站的问题,也可能是用户行为的差异,只有多观察一些网页才能综合抽象出具有普适性的关键字段——这并不是几分钟看几个网页就可以决定的简单事情,如果遇上了那种臃肿、混乱的网站,可能坑非常多。
对于大规模爬虫,除了本身要采集的数据外,其他重要的中间数据(比如页面Id或者url)也建议存储下来,这样可以不必每次重新爬取id。
数据库并没有固定的选择,本质仍是将Python里的数据写到库里,可以选择关系型数据库MySQL等,也可以选择非关系型数据库MongoDB等;对于普通的结构化数据一般存在关系型数据库即可。sqlalchemy是一个成熟好用的数据库连接框架,其引擎可与Pandas配套使用,把数据处理和数据存储连接起来,一气呵成。
数据流分析
对于要批量爬取的网页,往上一层,看它的入口在哪里;这个是根据采集范围来确定入口,比如若只想爬一个地区的数据,那从该地区的主页切入即可;但若想爬全国数据,则应更往上一层,从全国的入口切入。一般的网站网页都以树状结构为主,找到切入点作为根节点一层层往里进入即可。
值得注意的一点是,一般网站都不会直接把全量的数据做成列表给你一页页往下翻直到遍历完数据,比如链家上面很清楚地写着有24587套二手房,但是它只给100页,每页30个,如果直接这么切入只能访问3000个,远远低于真实数据量;因此先切片,再整合的数据思维可以获得更大的数据量。显然100页是系统设定,只要超过300个就只显示100页,因此可以通过其他的筛选条件不断细分,只到筛选结果小于等于300页就表示该条件下没有缺漏;最后把各种条件下的筛选结果集合在一起,就能够尽可能地还原真实数据量。
明确了大规模爬虫的数据流动机制,下一步就是针对单个网页进行解析,然后把这个模式复制到整体。对于单个网页,采用抓包工具可以查看它的请求方式,是get还是post,有没有提交表单,欲采集的数据是写入源代码里还是通过AJAX调用JSON数据。
同样的道理,不能只看一个页面,要观察多个页面,因为批量爬虫要弄清这些大量页面url以及参数的规律,以便可以自动构造;有的网站的url以及关键参数是加密的,这样就悲剧了,不能靠着明显的逻辑直接构造,这种情况下要批量爬虫,要么找到它加密的js代码,在爬虫代码上加入从明文到密码的加密过程;要么采用下文所述的模拟浏览器的方式。
数据采集
之前用R做爬虫,不要笑,R的确可以做爬虫工作;但在爬虫方面,Python显然优势更明显,受众更广,这得益于其成熟的爬虫框架,以及其他的在计算机系统上更好的性能。scrapy是一个成熟的爬虫框架,直接往里套用就好,比较适合新手学习;requests是一个比原生的urllib包更简洁强大的包,适合作定制化的爬虫功能。requests主要提供一个基本访问功能,把网页的源代码给download下来。一般而言,只要加上跟浏览器同样的Requests Headers参数,就可以正常访问,status_code为200,并成功得到网页源代码;但是也有某些反爬虫较为严格的网站,这么直接访问会被禁止;或者说status为200也不会返回正常的网页源码,而是要求写验证码的js脚本等。
下载到了源码之后,如果数据就在源码中,这种情况是最简单的,这就表示已经成功获取到了数据,剩下的无非就是数据提取、清洗、入库。但若网页上有,然而源代码里没有的,就表示数据写在其他地方,一般而言是通过AJAX异步加载JSON数据,从XHR中找即可找到;如果这样还找不到,那就需要去解析js脚本了。
解析工具
源码下载后,就是解析数据了,常用的有两种方法,一种是用BeautifulSoup对树状HTML进行解析,另一种是通过正则表达式从文本中抽取数据。
BeautifulSoup比较简单,支持Xpath和CSSSelector两种途径,而且像Chrome这类浏览器一般都已经把各个结点的Xpath或者CSSSelector标记好了,直接复制即可。以CSSSelector为例,可以选择tag、id、class等多种方式进行定位选择,如果有id建议选id,因为根据HTML语法,一个id只能绑定一个标签。
正则表达式很强大,但构造起来有点复杂,需要专门去学习。因为下载下来的源码格式就是字符串,所以正则表达式可以大显身手,而且处理速度很快。
对于HTML结构固定,即同样的字段处tag、id和class名称都相同,采用BeautifulSoup解析是一种简单高效的方案,但有的网站混乱,同样的数据在不同页面间HTML结构不同,这种情况下BeautifulSoup就不太好使;如果数据本身格式固定,则用正则表达式更方便。比如以下的例子,这两个都是深圳地区某个地方的经度,但一个页面的class是long,一个页面的class是longitude,根据class来选择就没办法同时满足2个,但只要注意到深圳地区的经度都是介于113到114之间的浮点数,就可以通过正则表达式"11[3-4].\d+"来使两个都满足。
数据整理
一般而言,爬下来的原始数据都不是清洁的,所以在入库前要先整理;由于大部分都是字符串,所以主要也就是字符串的处理方式了。
字符串自带的方法可以满足大部分简单的处理需求,比如strip可以去掉首尾不需要的字符或者换行符等,replace可以将指定部分替换成需要的部分,split可以在指定部分分割然后截取一部分。
如果字符串处理的需求太复杂以致常规的字符串处理方法不好解决,那就要请出正则表达式这个大杀器。
Pandas是Python中常用的数据处理模块,虽然作为一个从R转过来的人一直觉得这个模仿R的包实在是太难用了。Pandas不仅可以进行向量化处理、筛选、分组、计算,还能够整合成DataFrame,将采集的数据整合成一张表,呈现最终的存储效果。
写入数据库
如果只是中小规模的爬虫,可以把最后的爬虫结果汇合成一张表,最后导出成一张表格以便后续使用;但对于表数量多、单张表容量大的大规模爬虫,再导出成一堆零散的表就不合适了,肯定还是要放在数据库中,既方便存储,也方便进一步整理。
写入数据库有两种方法,一种是通过Pandas的DataFrame自带的to_sql方法,好处是自动建表,对于对表结构没有严格要求的情况下可以采用这种方式,不过值得一提的是,如果是多行的DataFrame可以直接插入不加索引,但若只有一行就要加索引否则报错,虽然这个认为不太合理;另一种是利用数据库引擎来执行SQL语句,这种情况下要先自己建表,虽然多了一步,但是表结构完全是自己控制之下。Pandas与SQL都可以用来建表、整理数据,结合起来使用效率更高。
‘柒’ 如何入门 Python 爬虫
Python入门程度的基础很简单:
1、简单的python语法,不需要什么很深的东西
2、请求库用法(requests、aiohttp等)
3、简单的抓包/抠URL
4、xpath、正则表达式的使用,且能在不用生成工具的情况下自己写出语句提取数据
以上四点已经足够让你爬一些简单的网站了,但仅仅是这个程度而已的话,就还没那些傻瓜式爬虫工具强呢。你还需要JavaScript/Android/iOS逆向知识(核心,杂七杂八的那些这里不一一列举,太多了),用于破加密请求参数、反爬等各种阻止你获取到数据的东西。
‘捌’ python爬虫入门需要哪些基础
现在之所以有这么多的小伙伴热衷于爬虫技术,无外乎是因为爬虫可以帮我们做很多事情,比如搜索引擎、采集数据、广告过滤等,以Python为例,Python爬虫可以用于数据分析,在数据抓取方面发挥巨大的作用。
但是这并不意味着单纯掌握一门Python语言,就对爬虫技术触类旁通,要学习的知识和规范还有喜很多,包括但不仅限于HTML 知识、HTTP/HTTPS 协议的基本知识、正则表达式、数据库知识,常用抓包工具的使用、爬虫框架的使用等。而且涉及到大规模爬虫,还需要了解分布式的概念、消息队列、常用的数据结构和算法、缓存,甚至还包括机器学习的应用,大规模的系统背后都是靠很多技术来支撑的。
零基础如何学爬虫技术?对于迷茫的初学者来说,爬虫技术起步学习阶段,最重要的就是明确学习路径,找准学习方法,唯有如此,在良好的学习习惯督促下,后期的系统学习才会事半功倍,游刃有余。
用Python写爬虫,首先需要会Python,把基础语法搞懂,知道怎么使用函数、类和常用的数据结构如list、dict中的常用方法就算基本入门。作为入门爬虫来说,需要了解 HTTP协议的基本原理,虽然 HTTP 规范用一本书都写不完,但深入的内容可以放以后慢慢去看,理论与实践相结合后期学习才会越来越轻松。关于爬虫学习的具体步骤,我大概罗列了以下几大部分,大家可以参考:
网络爬虫基础知识:
爬虫的定义
爬虫的作用
Http协议
基本抓包工具(Fiddler)使用
Python模块实现爬虫:
urllib3、requests、lxml、bs4 模块大体作用讲解
使用requests模块 get 方式获取静态页面数据
使用requests模块 post 方式获取静态页面数据
使用requests模块获取 ajax 动态页面数据
使用requests模块模拟登录网站
使用Tesseract进行验证码识别
Scrapy框架与Scrapy-Redis:
Scrapy 爬虫框架大体说明
Scrapy spider 类
Scrapy item 及 pipeline
Scrapy CrawlSpider 类
通过Scrapy-Redis 实现分布式爬虫
借助自动化测试工具和浏览器爬取数据:
Selenium + PhantomJS 说明及简单实例
Selenium + PhantomJS 实现网站登录
Selenium + PhantomJS 实现动态页面数据爬取
爬虫项目实战:
分布式爬虫+ Elasticsearch 打造搜索引擎
‘玖’ python爬虫的工作步骤
当前处于一个大数据的时代,一般网站数据来源有二:网站用户自身产生的数据和网站从其他来源获取的数据,今天要分享的是如何从其他网站获取你想要的数据。
目前最适合用于写爬虫的语言是python,python中最受欢迎的爬虫框架是scrapy,本文围绕scrapy来展开讲解爬虫是怎么工作的。
1.如下图所示,爬虫从编写的spider文件中的start_urls开始,这个列表中的url就是爬虫抓取的第一个网页,它的返回值是该url对应网页的源代码,我们可以用默认的parse(self,response)函数去打印或解析这个源代码
2.我们获取到源代码之后,就可以从网页源代码中找到我们想要的信息或需要进一步访问的url,提取信息这一步,scrapy中集成了xpath,正则(re),功能十分强大,提取到信息之后会通过yield进入到中间件当中。
中间件包括爬虫中间件和下载中间件,爬虫中间件主要用于设置处理爬虫文件中的代码块,下载中间件主要用于判断爬虫进入网页前后的爬取状态,在此中间件中,你可以根据爬虫的返回状态去做进一步判断。
最后我们将yield过来的item,即就是我们想要的数据会在pipeline.py文件中进行处理,存入数据库,写入本地文件,都可以在这里进行,另外,为了减少代码冗余,建议所有与设置参数有关的参数,都写在settings.py中去