本文章首次发表于我的个人网站 www.huqi.tk ,以下内容来自于我的个人网站www.huqi.tk 更多干货请访问www.huqi.tk
首先解释下什么是爬虫以及为何需要爬虫。爬虫定义:
一段自动抓取互联网信息的程序
这里为了让小白能够明白,没引用百度百科的定义。那么为何需要爬虫呢?我们知道互联网是由海量的网页组成,每一个网页都对应着一个url,每一个网页上也可能链接着其它的网页的url,每一个html网页上都展示着一些信息,如文本,图片等,当我们在浏览这些信息时,可能会发现很多我们感兴趣的数据,如心仪的妹子图,觉得这个妹子好漂亮,想把这张图片保存下来,当然如果只是几张妹子图,我们可以使用浏览器图片保存功能保存到磁盘,但是如果是几千张妹子图,我们手动的一个一个保存岂不….,因此我们会想要是能够有一个自动帮我们抓取网页妹子的程序帮我们来完成这个过程,我们只管欣赏妹子多好。对这就是爬虫,爬虫能够从一个页面的url开始,不断的爬取与之相关联的所有的url,且能够抓取我们感兴趣的有价值的数据,如妹子图。当然这只是一个简单的例子而已,事实上爬虫的功能远远不止爬取妹子图这么简单,爬虫在搜索引擎中也能够大显身手,总之爬虫的价值在于让互联网上的数据为我们所用。
好了说明了什么是爬虫以及为何需要爬虫,现在就来实现一个简单的给小白看的入门的爬取妹子图的爬虫程序,那么一个简单的爬虫程序需要哪些部分组成呢?还是按照上面的例子来看,既然爬虫是从一个网页开始不断爬取与之关联的url,然后抓取我们感兴趣的数据,那么首先就需要抓取网页,然后解析网页的内容,这样才能找出我们感兴趣的内容,同时还需要知道哪些网页已经爬取过了,哪些网页未爬取,因为网页之间的url可能会互相指向,因此要保存那些已经爬取了的url,爬取过的就不在爬取,同时新爬取的网页上可能存在指向新的网页的url,因此需要把新的url保存起来用来下一轮进行爬取。因此至少要包括网页下载器,网页解析器和Url管理器,一个用来抓取网页,将互联网上的网页以html的形式抓取下来,一个用来解析网页数据,从抓取到的html文件中寻找我们感兴趣的数据,一个用来管理已爬取的url和新增加的url。既然是写给小白看的,那么初次就不搞那么复杂,我们首先选择一个网页爬取,然后逐渐扩充其功能。这样能够让小白更加容易明白,当你看完了本教程,觉得原来爬虫也没那么难,那就达到我们的目的了。下面就进入正题,开始抓取我们心仪的妹子图之旅吧。
python中抓取网页使用urllib2,该模块是官方内置的,网页的解析使用BeautifulSoup,该模块是一个第三方库,使用时需要先安装该库,我们一个一个来看:
urllib2/requests
- urllib2是python官方的url模块,因为是官方内置的,所以使用时只需要要import urllib2即可
- requests是第三方的lib,相对urllib2功能更加强大
因此是给小白看的,所以本文章以urllib2为例进行讲解,首先我们来看一下urllib2中一些重要的函数
urlopen
- geturl()返回实际检索的url,因为如果出现重定向,请求的url可能和获取的url不一样
- info()返回网页的meta信息,如headers
- getcode()返回响应的http请求的状态码,如果该值为200表示请求成功
如果调用出现错误,会抛出URLError,如:请求的url不存在,因此对于该函数的使用需要tyr/except。常用代码如下:
root_url='http://www.baidu.com' try: response = urllib2.urlopen(root_url) if response.getcode() == 200: print response.read() except urllib2.URLError,e: print e
注意当进行http请求时,url中的http://必须加上,不能写成root_url=’www.baidu.com’,否则会出现unknow url type.
这是因为该函数不仅支持http访问,还支持ftp,本地文件访问等(只需要将url中的http替换为ftp或file即可),因此必须在参数中指定是哪种请求。
Request
那如果我们要添加header信息或者post请求添加data呢?前面说过urlopen函数的参数为一个url字符串或者Request对象,此时我们需要使用Request对象,其定义如下:
urllib2.Request(url[, data][, headers][, origin_req_host][, unverifiable])
其中除了url参数外,其余几个参数都是可选的,一般用的比较多的是前面三个参数,即url,data,header,即请求网址,请求数据和请求头部信息。其中data和headers除了在构造对象时传递外,还可以通过add_data(),add_header()函数添加。因此我们可以先构造一个Request对象,在该对象中添加data和header信息,然后将其传给urlopen作为参数,常用代码如下:
root_url='http://www.baidu.com' user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)' values = {'site': 'www.huqi.tk', 'language': 'Python'} headers = {'User-Agent': user_agent} data = urllib.urlencode(values)#将字典格式转化为http请求格式,通常是一系列的以&隔开的key=value对 request = urllib2.Request(root_url, data, headers) try: response = urllib2.urlopen(request) if response.getcode() == 200: print response.read() except urllib2.URLError,e: print e
需要注意的是在传递data之前,需要将传递的dict数据转化为http请求格式的数据,即urllib.urlencode(),该函数定义如下:
urllib.urlencode(query)
该函数用来将一个映射对象或者两个元素的元组转换为http请求格式的字符串,通常是一系列的以&隔开的key=value对(The resulting string is a series of key=value pairs separated by ‘&’ characters)
BeautifulSoup
是用Python写的一个HTML/XML的解析器,该解析器会将html/xml文件看作一个DOM(Document Object Model)树,每一个html中的节点标签类似一棵树的节点。因此这是一种结构化的解析方式。下面我们来了解下如何使用。
这是文档官方网址:https://www.crummy.com/software/BeautifulSoup/bs4/doc/。
BeautifulSoup的使用一般遵循如下几个步骤
- 构造一个BeautifulSoup对象
- 搜索节点,其中搜索节点可以按照节点名称如html中的<a>,<div>标签,节点属性如href或者class属性,节点的内容三个方面来搜索,主要涉及的函数是find和find_all
- 访问节点的属性,内容,当搜索到了对应的节点之后就可以访问节点的内容。
下面一一介绍:
BeautifulSoup(html_doc,’html.parser’,from_encoding=’utf-8′)
soup = BeautifulSoup(response.read(), 'html.parser', from_encoding='utf-8')
其中response是前面讲到的urlopen打开url后获得的文件对象。
find/find_all
- find() 返回文档中符合条件的tag,如果没找到符合条件的tag返回Node
- find_all()返回文档中全部符合条件的tag的列表,如果不存在返回空列表
注意find()函数返回的是符合条件的tag,因此可以进行链式调用,如:
#先查找class属性为‘post-content’的div标签,然后查找该div标签下的所有的img标签 soup.find('div', class_='post-content').find_all('img')
而find_all()返回的是列表,列表是不存在find()和find_all()函数的,因此不能进行链式调用
好了基本原理都讲完了,赶快来抓取我们心仪的妹子哦,只需简单的几个步骤,心仪的妹子图就到碗里来了哦!
首先找一个心仪的妹子,这个就看个人喜好了,看谁是你心中女神了,看谁长的漂亮啦,比如刘诗诗啦,这里少年就以少年心中的女神90后演员杨紫(因为喜欢她在青云志中饰演的陆雪琪)为例。首先我们在浏览器中打开心仪妹子图网址http://iyangzi.com/?p=173,然后在心仪的图片上右键选择检查元素,或者直接按F12,就可以看到网页的源代码了,然后点击那个带箭头的选项,如图:
然后你会发现当鼠标在左侧区域移动时右侧的源代码区也会随之移动定位到对应位置,这样我们就可以找出心仪的妹子图片位于那个tag下,如图通过多次移动我们发现妹子图位于<div class=”post-conten”>的<p>tag下,如图:
找到了我们感兴趣的数据之后,我们就可以写一个爬虫程序自动为我们抓取心仪的妹子图哦,然后将抓取的妹子图保存到我们的磁盘上就可以了哦,代码如下:
#coding:utf-8 import os import urllib2 from bs4 import BeautifulSoup root_url='http://iyangzi.com/?p=173' try: response = urllib2.urlopen(root_url) if response.getcode()==200: girl_dir = 'C:\Users\htq\Desktop\girl' if not os.path.exists(girl_dir): os.mkdir(girl_dir) os.chdir(girl_dir) soup = BeautifulSoup(response.read(), 'html.parser', from_encoding='utf-8') all_img = soup.find('div', class_='post-content').find_all('img') count = 1 for img in all_img: src = img['src'] #print src name = 'iyangzi' + str(count) with open(name + '.jpg', 'ab') as img_object: img_content = urllib2.urlopen(src).read() img_object.write(img_content) img_object.flush() count += 1 except urllib2.URLError,e: print e
代码是不是很简单,基本上就是前面介绍的那些知识点,然后运行程序可以看到,控制台输出了妹子图的网络地址
在磁盘的C:\Users\htq\Desktop\girl目录下已经自动帮我们保存好了心仪的妹子图片哦,还不赶快去欣赏欣赏。
好了,一个简单的入门级的抓取妹子图的爬虫就写好了,嗯,不仅学会了写爬虫,还收获了妹子图,简直不要太激动,小伙伴们赶快去试试抓取自己心仪的女神的图片欣赏吧。
当然这只是简单的讲解了爬虫的原理,爬虫远不止这么简单,如前面说的爬取互联网上海量的url的数据,对已爬取和新增加的url进行管理等,再如某些网站会进行反爬虫,因此面对这种情况我们需要应对反爬虫,再如使用多线程或者多进程提高效率,再如使用爬虫框架等等,这些内容将会以爬虫系列的形式进行讲解,希望大家后期继续关注,多多支持!