在互联网时代,爬虫绝对是一项非常有用的技能。借助它,你可以快速获取大量的数据并自动分析,或者帮你完成大量重复、费时的工作,分分钟成为掌控互联网的大师。
注意:欲获取本文所涉及的文案,代码及教学视频的链接,请移步留言区。这是我们第一次录制教学视频来帮助大家更好的学习技术,该视频的录制耗时超过八个小时。
什么是爬虫?
-- 爬虫,即网络爬虫,大家可以理解为在网络上爬行的一只蜘蛛,互联网就比作一张大网,而爬虫便是在这张网上爬来爬去的蜘蛛咯,如果它遇到资源,那么它就会抓取下来。想抓取什么?这个由你来控制。
-- 比如它在抓取一个网页,在这个网中他发现了一条道路,其实就是指向网页的超链接,那么它就可以爬到另一张网上来获取数据。这样,整个连在一起的大网对这之蜘蛛来说触手可及,分分钟爬下来不是事儿。 -- 在用户浏览网页的过程中,我们可能会看到许多好看的图片,比如
,我们会看到几张的图片以及百度搜索框,这个过程其实就是用户输入网址之后,经过DNS服务器,找到服务器主机,向服务器发出一个请求,服务器经过解析之后,发送给用户的浏览器 HTML、JS、CSS 等文件,浏览器解析出来,用户便可以看到形形色色的图片了。
-- 因此,用户看到的网页实质是由 HTML 代码构成的,爬虫爬来的便是这些内容,通过分析和过滤些 HTML 代码,实现对图片、文字等资源的获取。
那URL又是什么呢?
-- URL,即统一资源定位符,也就是我们说的网址,统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
-- URL的格式由三部分组成:
1是协议(或称为服务方式)。
2是存有该资源的主机IP地址(有时也包括端口号)。
3是主机资源的具体地址,如目录和文件名等。
爬虫爬取数据时必须要有一个目标的URL才可以获取数据,因此,它是爬虫获取数据的基本依据,准确理解它的含义对爬虫学习有很大帮助。
看完了上面的介绍,小伙伴们是不是已经迫不及待想要搞搞事情了呢?
下面正式为你们介绍如何利用爬虫获取资源
①环境配置
学习Python,当然少不了环境的配置。要使用python进行各种开发和科学计算,还需要安装对应的包。在这里给大家推荐Anaconda,它把需要的包都集成在了一起,因此我们实际上从头到尾只需要安装Anaconda软件就行了,而且Anaconda自带编译器spyder。下载地址:
下载安装包名称为:Anaconda3-5.0.0-Windows-x86_64.exe
按照正常步骤安装即可,
注意事项
将两个选项都选上,将安装路径写入环境变量 然后等待安装完成就行了。
如何管理python包?
安装一个包:
conda install package_name
移除一个包:
conda remove package_name
升级包版本:
conda update package_name
查看所有的包:
conda list
这样就可以将包安装进Anaconda里面,如果你要想把包安装进自己的系统里面的话就用pip命令了。
安装完Anaconda后,我们就可以用自带的spyder编译器来写代码了。
好了,环境配置好了。接下来跟着小编的步伐一起来搞点事情吧。
②确定URL并抓取页面代码
糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把,现在我们尝试抓取一下糗事百科的热门段子吧,每按下一次回车我们显示一个段子。
首先我们确定好页面的URL是
其中最后一个数字1代表页数,我们可以传入不同的值来获得某一页的段子内容。我们初步构建如下的代码来打印页面代码内容试试看,先构造最基本的页面抓取方式。
代码语言:javascript复制import urllib
import urllib.request
page = 1
user_agent = 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:56.0)
Gecko/20100101 Firefox/56.0'
//模拟浏览器的头
headers = { 'User-Agent' : user_agent }
try:
request = urllib.request.Request(url,headers = headers)
response = urllib.request.urlopen(request)
print(response.read())
except urllib.request.URLError, e:
if hasattr(e,"code"):
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
③提取某一页的所有段子
进入糗事百科的界面,我们打开浏览器自带的WEB查看器
我们可以看到,每一个段子都是<div class=”article block untagged mb15″ id=”…”>…</div>包裹的内容。
现在我们想获取发布人,发布日期,段子内容,以及点赞的个数。不过另外注意的是,段子有些是带图片的,如果我们想在控制台显示图片是不现实的,所以我们直接把带有图片的段子给它剔除掉,只保存仅含文本的段子。
所以我们加入如下正则表达式来匹配一下,用到的方法是 re.findall 是找寻所有匹配的内容。
代码语言:javascript复制content = response.read().decode('utf-8')
//已经爬取的网页内容
代码语言:javascript复制pattern = re.compile('<div.*?author">.*?<a.*?<img.*?>(.*?)</a>.*?<div.*?'
'content">(.*?)<!--(.*?)-->.*?</div>(.*?)<divclass="stats.*?class="number">(.*?)</i>',re.S)
items = re.findall(pattern,content)
for item in items:
print(item[0],item[1],item[2],item[3],item[4])
现在正则表达式在这里稍作说明
1).*? 是一个固定的搭配,.和*代表可以匹配任意无限多个字符,加上?表示使用非贪婪模式进行匹配,也就是我们会尽可能短地做匹配,以后我们还会大量用到 .*? 的搭配。
2)(.*?)代表一个分组,在这个正则表达式中我们匹配了五个分组,在后面的遍历item中,item[0]就代表第一个(.*?)所指代的内容,item[1]就代表第二个(.*?)所指代的内容,以此类推。
3)re.S 标志代表在匹配时为点任意匹配模式,点 . 也可以代表换行符。这样我们就获取了发布人,发布时间,发布内容,附加图片以及点赞数。
在这里注意一下,我们要获取的内容如果是带有图片,直接输出出来比较繁琐,所以这里我们只获取不带图片的段子就好了。在这里我们就需要对带图片的段子进行过滤。
我们可以发现,带有图片的段子会带有类似下面的代码,而不带图片的则没有,我们的正则表达式的item[3]就是获取了下面的内容,如果不带图片,item[3]获取的内容便是空。
所以我们只需要判断item[3]中是否含有img标签就可以了。
我们再把上述代码中的for循环改为下面的样子
代码语言:javascript复制for item in items:
haveImg = re.search("img",item[3])
if not haveImg:
print(item[0],item[1],item[2],item[4])
4. 完善交互,设计面向对象模式
现在最核心的部分我们已经完成啦,剩下的就是修一下边边角角的东西,我们想达到的目的是:
按下回车,读取一个段子,显示出段子的发布人,发布日期,内容以及点赞个数。
另外我们需要设计面向对象模式,引入类和方法,将代码做一下优化和封装,最后,我们的代码如下所示:
代码语言:javascript复制import urllib.request
import re
import _thread
import time //调用的包
#----------- 加载处理糗事百科 -----------
class Spider_Model:
def __init__(self):
self.page = 1
self.pages = []
self.enable = False
# 将所有的段子都扣出来,添加到列表中并且返回列表
# 用于加载新的段子
代码语言:javascript复制 def LoadPage(self):
# 如果用户未输入quit则一直运行
while self.enable:
# 如果pages数组中的内容小于2个
if len(self.pages) < 2:
try:
# 获取新的页面中的段子们
myPage = self.GetPage(str(self.page))
self.page = 1
self.pages.append(myPage)
except:
print ('无法链接糗事百科!' )
else:
time.sleep(1)
def ShowPage(self,nowPage,page):
for items in nowPage:
print (" ", items)
myInput = input()
if myInput == "quit":
self.enable = False
break
def Start(self):
self.enable = True
page = self.page
print(page)
print (u'正在加载中请稍候......')
# 新建一个线程在后台加载段子并存储
_thread.start_new_thread(self.LoadPage,())
#----------- 加载处理糗事百科 -----------
while self.enable:
# 如果self的page数组中存有元素
if self.pages:
nowPage = self.pages[0]
del self.pages[0]
self.ShowPage(nowPage,page)
page = 1
#----------- 程序的入口处 -----------
print (u"""
代码语言:javascript复制---------------------------------------
程序:糗百爬虫
日期:2017-10-23
语言:Python 3.5.2
操作:输入quit退出阅读糗事百科
功能:按下回车依次浏览今日的糗百热点
---------------------------------------
""")
print( u'请按下回车浏览今日的糗百内容:' )
input(' ')
myModel = Spider_Model()
myModel.Start()
效果展示
来看看我们的程序的演示效果吧
自从有了这个爬虫以后,层出不穷的段子供你欣赏哦!
而且大家还可以根据自己喜好把段子输出成文件或者把程序打包成exe文件,具体的做法会在以后给出。
相关资料请移步留言区。