python小程序:豆瓣图书的网络爬虫

学习 python 有一段时间,一直都是看书学,写点书上的小例子,终于把书看完了,想着写一个爬虫锻炼一下。其实用 python 写爬虫还是挺简单的,一个难点是正则表达式,因为一般用 python 把网页整个源代码爬下来,然后根据网页的内容结构把我们需要的内容给抓出来。作为一名后端程序员,平时也只是偶尔写写前端页面,偶尔遇上一些需要正则表达式的,也就是在网上找了一下,没有怎么学,所以写这个之前还补了一下正则表达式。

urllib2模块和urllib模块类似,用来打开URL并从中获取数据。与urllib模块不同的是,urllib2模块不仅可以使用urlopen()函数还可以自定义opener来访问网页。但同时要注意:urlretrieve()函数是urllib模块中的,urllib2模块中不存在该函数。但是使用urllib2模块时一般都离不开urllib模块,因为post的数据需要使用urllib.urlencode()函数来编码。

先来介绍一下程序中用到的urllib2方法: urlopen(url, [,data, [timeout]]) urlopen()是最简单的请求方式,它打开url并返回类文件对象,并且使用该对象可以读取返回的内容。参数url可以是包含url的字符串,也可以是urllib2.request类的实例。data是经过编码的post数据(一般使用urllib.urlencode()来编码)。timeout是可选的超时期(以秒为单位),供所有阻塞操作内部使用。 假设urlopen()返回的文件对象u,它支持下面的这些常用的方法: u.read([nbytes]) 以字节字符串形式读取nbytes个数据 u.readline() 以字节字符串形式读取单行文本 u.readlines() 读取所有输入行然后返回一个列表 u.close() 关闭链接 u.getcode() 返回整数形式的HTTP响应代码,比如成功返回200,未找到文件时返回404 u.geturl() 返回所返回的数据的实际url,但是会考虑发生的重定向问题 u.info() 返回映射对象,该对象带有与url关联的信息,对HTTP来说,返回的服务器响应包含HTTP包头。对于FTP来说,返回的报头包含’content-length’。对于本地文件,返回的报头包含‘content-length’和’content-type’字段。 要注意的是,类文件对象u以二进制模式操作。如果需要以文本形式处理响应数据,则需要使用codecs模块或类似方式解码数据。

关于正则表达式,可以参考一下这篇文章:Python正则表达式指南

需要注意的是是否匹配多行模式以及贪婪模式与非贪婪模式。

二、这个衔接是《暗时间》的豆瓣介绍

http://book.douban.com/subject/6709809/

通过查看源码分析,就会发现

有class=”ua-windows ua-webkit book-new-nav”的页面是图书介绍页面,而其中标题结构为暗时间 (豆瓣) 出版社、出版年、页数、定价等结构如下: 出版社 (.*)

稍微难一点的是作者:

作者:

刘未鹏


涉及到了换行,开始使用

作者.<a class="" href=.>(.*)去匹配,查出来的作者不是空就是豆瓣广告,这首因为默认使用贪婪模式匹配,后来改成如下使用非贪婪模式就正确了

作者.?<a class="" href=.?>(.*?)

全部代码如下:

#coding=utf-8
"""
这是一个抓取豆瓣图片源代码,并从中提取相关内容的python小爬虫
"""
import sys
import urllib2
import re

def get_book(packet):
    tmp = re.search(r'',packet)
    if tmp is not None:
        print "It's Book"
        title = re.search(r'(.*)\(豆瓣\)',packet)
        print '书名:' + title.group(1).strip()
        author = re.search(r' 作者.*?(.*?)',packet,re.S)
        if author:
            print '作者:' + author.group(1).strip()
        cbs = re.search(r'出版社:(.*)
',packet) if cbs: print '出版社:' + cbs.group(1).strip() price = re.search(r'定价:(.*)
',packet) print '定价:' + price.group(1).strip() else: print "It's not Book" def douban_book(url): try: response = urllib2.urlopen(url) content = response.read() get_book(content) except urllib2.URLError,e: if hasattr(e,"reason"): print 'Failed to reach the server' print "The reason:",e.reason elif hasattr(e,"code"): print "The server couldn't fulfill the request" print "Error code:",e.code print "Return content:",e.read() else: pass if __name__ == '__main__': url = 'http://book.douban.com/subject/222222/' packet = douban_book(url) if packet is None: sys.exit(0)

结果如下图所示:

douban

拓展:可以看到豆瓣图书的url都是http://book.douban.com/subject/加上一个数字,所以可以写一个循环,就可以统计一下豆瓣有多少图书了,有空试一下。

评论

  1. GSM
    11 年前
    2014-8-28 10:17:26

    可以看到豆瓣图书的url都是http://book.douban.com/subject/加上一个数字,所以可以写一个循环,就可以统计一下豆瓣有多少图书了,有空试一下。
    这个是不太准确的,因为有很多是not found。因为豆瓣的连接是http://xxx.douban.com/subject/+数字
    XXX 可以是movie,book…

    • tcxurun
      博主
      GSM
      11 年前
      2014-8-31 18:49:56

      嗯,你说的我知道,循环里面要进行判断的,如果是not found就排除掉,不算统计的。

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇