rainbowzc

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: :: :: 管理 ::
我还年轻 , 我渴望上路 ...
                                                                      - <在路上>

引子


当Google创始人用python写下他们第一个简陋的爬虫, 运行在同样简陋的服务器上的时候 ;
很少有人能够想象 , 在接下的数十年间 , 他们是怎样地颠覆了互联网乃至于人类的世界 ;

今天 , 我们谨以一只小小的python爬虫 , 作为我们的第一个编程作品 ;纪念并缅怀那个从python开始征途的伟大搜索引擎


注 : 上图为Google的最初机房

预习材料


* python科普
* 易百python教程
* 笨方法学python
* 两个小时学会python 作者 : 刘鑫
* Python 2.7 官方教程 中英文对照版本
* 正则表达式
* [英文] codecademy python 教程

课前准备


python : 我们最爱的编程语言

进入pyhon官网,选择你所需要的版本,进行下载安装。

python安装完毕之后,会在开始菜单的python中,看到python帮助手册。
帮助手册可以作为案头书,帮助我们快速查找。

如下图 :我们对with 语句不熟悉,就可以实用帮助手册的索引,快速查到相应的文档。


ulipad : python代码编辑器


ulipad 是一个很好用的python编辑器。跨平台,使用wxPython 编写。

作者,limodou 。

我们从源码进行安装。

首先,安装:

    * comtypes
    * wxPython

然后,下载ulipad

解压后运行ulipad.pyw

ulipad提供了代码的编辑,提示,运行,调试多种功能。


easy_install :python的包管理命令


setuptools 是python的包管理器 , 对应的命令是 easy_install 。

什么 , 你存在了这么多年还不知道什么叫做 “包管理”  !!!

包管理 就是 360的软件管家 !!!

它可以帮我们 安装 , 更新 软件(或 代码库)。

下载脚本 ez_setup.py , 安装 easy_install

windows用户按 Window键 + R , 输入cmd打开命令行窗口

setuptools 用法如下 :

     * 安装模块 :
        easy_install 包的名称

    * 强制 更新/重装 python的模块 :
        easy_install -U 包的名称

requests : for Humans 的 网络库


requests是一个github[注1]上排名前100名的项目。

官方的文档 在自己首页昭告天下 :

    Requests : HTTP for Humans

于是我意识到 , 这货是为地球人准备的网络库。我们用它来在python中读取网页。

先切换到easy_install的安装目录中 , 然后执行 :
easy_install requests

如图:  


wget : 命令行的下载工具



wget是Linux中的下载工具。我们也可以在windows上使用它。

首先 , 下载wget的windows版本。

然后 , 将文件解压到C:\WINDOWS下,就可以直接在命令行中使用wget。

下面我们用wget下载一个我们即将用到的python模块。

在终端下:
wget http://school-src.42qu.com/1_spider/extract.py
即可。

firebug: 前端工程师的神器


Firebug是Firefox的插件 , 前端工程师的神器 。

记得用 Firefox安装 , 亲。

Firebug有多个控制面板,常用的有html,net ,console。

使用html面板我们可以查看整个dom的文档树。


通过net面板我们可以查看到http的请求。


爬虫是什么?


有网络的地方就有爬虫,爬虫英文名称spider,有时也叫它机器人(bot)。它是用来抓取网站数据的程序。

比如: 我们通过一段程序,定期去抓取类似美团,拉手网上的数据,将这些信息存储到数据库里,然后加上展示页面,一个团购导航站就问世了。

毫无疑问,爬虫是很多网站的初期数据来源。

先不说,google,百度这样的以爬虫起家的搜索引擎,就连豆瓣这样的文艺小清新网站,也需要爬虫去抓取图书,唱片的基本信息。



今天我们就以 落网 为例,来实现一个下载mp3的小爬虫。

首先, 右键点击网页上的元素,用Firebug的inspect工具审查元素。


我们发现落网的歌曲是通过一个<iframe>标签内嵌一个flash的播放器来播放的。

于是,我们将iframe中的src(http://www.luoo.net/radio/radio395/mp3.xml)提取出来




新开一个页面,打开链接,一下子好清爽,页面上只有一个播放器了,而我们所要的歌曲名和下载地址也都在这个播放器中。


继续使用firebug,将panel切换到Net。


因为刚才我们浏览页面的时候,已经访问过395,数据被浏览器缓存,刷新的时候就看不到全部请求。

我们将网址的395 换成394

刷新 http://www.luoo.net/radio/radio394/mp3.xml

Firebug的NET标签中中列出了所有的请求。其中有一个叫做mp3.xml的链接。


新标签页打开,没错,这就是我们要找的东西。



打开这个xml页面,其中是一个个

<song id="01" path="http://ftp.luoo.net/radio/radio395/01.mp3" title="小木船"/>

这种标签。 path 和title就是所需的数据。

但总不能这么手工下载吧。

爬虫代码,我来了 ^_^

不过在此之前,请你先认真阅读预习材料,对python的语言有个基本的认识。

爬虫代码


首先,下载一个extract库文件

在同一层目录下用ulipad编辑下面的代码
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
#! /usr/bin/env python
#coding=utf-8
  
import requests
from os.path import dirname, abspath
from extract import extract, extract_all
import re
RE_CN = re.compile(ur'[\u4e00-\u9fa5]+')
PREFIX = dirname(abspath(__file__))
  
with open("%s/down.bat"%PREFIX,"w") as down:
    for i in xrange(1, 396):
        for url in (
            'http://www.luoo.net/radio/radio%s/mp3.xml'%i,
        ):
  
            r = requests.get(url)
            print url
            if r.status_code == 200:
                for path, name in zip(
                    extract_all('path="', '"', r.content),
                    extract_all('title="', '"', r.content)
                ):
                    if RE_CN.match(name.decode('utf-8', 'ignore')):
                        down.write('wget %s -O "%s/%s.mp3"\n'%(
                           path,PREFIX,name.decode('utf-8',
                            "ignore").encode("gb18030","ignore")))
                break

建议大家用ulipad新建文档,手写一遍代码!!!

再强调一遍,手写!!!不要复制粘贴!!!

代码分析


因为我们的目的是下载落网上的所有中文歌曲。所以这里要做的工作主要分为三个部分。
首先,我们要对目标网址发出请求,获取它的反馈。这里就是requests这个库的作用了。
1
2
r = requests.get(url)
     if r.status_code == 200:
使用get方法,我们得到一个requests对象,如果status_code == 200 说明请求成功。

接下来就是分析返回值了。

这里用到了一个extract_all函数,它可以遍历整个返回文档,返回一个列表,里面包含我们提供的两个参数的中间部分字符串。

extract_all('path="', '"', r.content),

获取到值之后,我们就要对值进行一下过滤了。因为我们只想获得中文的歌曲。

这里就用到了正则表达式:
1
RE_CN.match(name.decode('utf-8', 'ignore'))

它会对匹配中文字符串,如果是中文,我们就把它写到文件中。

正则表达式 是 程序员 的 基本功 , 请认真阅读 Python正则表达式操作指南

在写文件这一步,我们还做了一个处理
1
PREFIX = dirname(abspath(__file__))

其中 __file__ 是python的一个内置变量。表示的是当前运行的文件名。
通过 dirname(abspath(__file__))我们就可以把爬虫文件和将要下载的mp3文件都在同一个目录下。

运行爬虫


在ulipad中点击运行,我们的爬虫就开始爬动了。因为它还很小,还不懂什么多线程,所以速度还比较慢,稍等片刻后,我们会生成一个down.bat文件。
双击这个bat文件,我们的MP3就开始下载了。


课后练习


自己实现 extact 和 extact_all  函数
下载中关村壁纸站的所有壁纸

扩展阅读


The Hitchhiker’s Guide to Python!

注:
1.github是全世界最大的程序员代码版本控制网站
posted on 2013-12-25 23:21  ct  阅读(6578)  评论(0编辑  收藏  举报