最近想做一个小web应用,就是把豆瓣读书和亚马逊等写有书评的网站上关于某本书的打分记录下来,这样自己买书的时候当作参考。

这篇日志这是以豆瓣网为例,只讨论简单的功能。

向服务器发送查询请求

这很好处理,找到网站的搜索框,然后填入相关信息,提交后查看url即可。

这里以豆瓣为例,当我在http://book.douban.com页面的搜索框中输入 现代操作系统 后得到下面的url:

http://book.douban.com/subject_search?search_text=%E7%8E%B0%E4%BB%A3%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F&cat=1001

这样就知道如何向服务器提交查询请求了,注意search_text后面的一串字符只是编码不同(。。。)。

利用Urllib2和Urllib库发送和获取HTTP页面

详见下面代码:

book_name = '现代操作系统'
douban_book = 'http://book.douban.com/subject_search?'
search = [('search_text','现代操作系统'),('cat','1001')]
getbook = douban_book + urllib.urlencode(search)
content = urllib2.urlopen(getbook).read()

利用SGMLParser库解析HTTP文本

  1. 第一步,利用浏览器自带的查看页面信息的工具,查看页面布局。
  2. 根据布局,思考解析的方法。这一步很主要,决定了第三步的效率
  3. 编写代码。基本上就是重写SGMLParser子类的方法。

详细代码

代码写的很乱,一些语法还不是很熟悉。我是以写代码来学习Python的,什么不懂就查什么。

# -*- coding: utf-8 -*-
import urllib2
import urllib
from sgmllib import SGMLParser class BookInfo(SGMLParser):
def reset(self):
SGMLParser.reset(self)
# 标记对应的标签
self.is_subject = 0
self.is_subject_info = 0
self.is_subject_h2 = 0
self.is_subject_pub = 0
self.is_subject_star = 0 self.temp = {} # 一个字典,保存暂时的信息
self.info = [] # 一个列表,保存所有的信息 # li标签开始出现
def start_li(self,attrs):
if 'subject-item' in [v for k, v in attrs if k == 'class']:
self.is_subject = 1
# li标签结束
def end_li(self):
self.is_subject = 0 def start_h2(self,attrs):
if self.is_subject == 1 and '' in [v for k,v in attrs if k == 'class']:
self.is_subject_h2 = 1 def end_h2(self):
self.is_subject_h2 = 0 def start_div(self,attrs):
attr = ''
for k,v in attrs:
if k == 'class':
attr = v
break
if attr == 'info' and self.is_subject == 1:
self.is_subject_info = 1
elif attr == 'pub' and self.is_subject_info == 1:
self.is_subject_pub = 1
elif attr == 'star clearfix' and self.is_subject_info == 1:
self.is_subject_star = 1
else:
pass
def end_div(self):
if self.is_subject_star == 0:
if self.is_subject_pub == 0:
self.is_subject_info = 0
self.info.append(self.temp)
self.temp = {}
else:
self.is_subject_pub = 0
else:
self.is_subject_star = 0 def handle_data(self,data):
if self.is_subject_h2:
string = data.strip()
if len(string):
if 'name' in self.temp:
self.temp['name'] = self.temp['name'] + string
else:
self.temp['name'] = string
#print string
elif self.is_subject_pub:
string = data.strip()
if len(string):
if 'pub' in self.temp:
self.temp['pub'] = self.temp['pub']+string
else:
self.temp['pub'] = string
elif self.is_subject_star:
string = data.strip()
if len(string):
if 'star' in self.temp:
self.temp['star'] = self.temp['star'] + string
else:
self.temp['star'] = string
#print string
else:
pass book_name = '现代操作系统'
douban_book = 'http://book.douban.com/subject_search?'
search = [('search_text','现代操作系统'),('cat','1001')]
getbook = douban_book + urllib.urlencode(search)
print getbook
content = urllib2.urlopen(getbook).read()
fobj = open('book.txt','w')
fileobj = open('books.txt','w')
book = BookInfo()
book.feed(content)
for books in book.info:
for item in books:
print '*************************************************'
print '书名:%s' % books['name']
if 'pub' in books:
print '出版信息:%s' % books['pub']
if 'star' in books:
print '评价:%s' % books['star']
break
fobj.write(content)
fobj.close()
fileobj.close()

输出结果

这只是开头的第一步,以后的日子里不断的学习和实践。。。

Bug修复和改进

上面的代码其实还是有问题的,只是没用被发现。当标记第一个 div 标签的确是没用问题,但是当出现第二个div标签时,如果第 二个是第一个的子元素,那么当处理第二个子标签的/div 闭合标签的时候就会出错。

一个小小的改进。这个程序严格要求输入的是正确的书名,这样处理的结果才是正确的。如果不是完全正确的书名,我的代码量就成集合倍增加了。在豆瓣读书中,评价书小于特定的数目时,是没有评论的(代表这个版次的书一般是很久的,上个世纪的书了),那么就没有参考价值了。

下面是修改后的代码:

# -*- coding: utf-8 -*-
import urllib2
import urllib
from sgmllib import SGMLParser class BookInfo(SGMLParser):
def reset(self):
SGMLParser.reset(self)
# 标记对应的标签
self.is_subject = 0
self.is_subject_info = 0
self.is_subject_h2 = 0
self.is_subject_pub = 0
self.is_subject_star = 0
self.is_subject_rating = 0 self.temp = {} # 一个字典,保存暂时的信息
self.info = [] # 一个列表,保存所有的信息 # li标签开始出现
def start_li(self,attrs):
if 'subject-item' in [v for k, v in attrs if k == 'class']:
self.is_subject = 1
# li标签结束
def end_li(self):
self.is_subject = 0 def start_h2(self,attrs):
if self.is_subject == 1 and '' in [v for k,v in attrs if k == 'class']:
self.is_subject_h2 = 1 def end_h2(self):
self.is_subject_h2 = 0 def start_div(self,attrs):
attr = ''
for k,v in attrs:
if k == 'class':
attr = v
break
if attr == 'info' and self.is_subject == 1:
self.is_subject_info = 1
elif attr == 'pub' and self.is_subject_info == 1:
self.is_subject_pub = 1
elif attr == 'star clearfix' and self.is_subject_info == 1:
self.is_subject_star = 1
else:
pass
def end_div(self):
if self.is_subject_info:
if self.is_subject_pub:
if self.is_subject_star:
self.is_subject_star = 0
self.is_subject_rating = 0
else:
self.is_subject_pub = 0
elif self.is_subject_star:
self.is_subject_star = 0
self.is_subject_rating = 0
if len(self.temp) == 3:
self.info.append(self.temp)
self.temp = {}
else:
self.is_subject_info = 0
def start_span(self,attrs):
if self.is_subject_star and 'allstar45' in [v for k,v in attrs if k == 'class']:
print [v for k,v in attrs if k == 'class']
self.is_subject_rating = 1 def handle_data(self,data):
if self.is_subject_h2:
string = data.strip()
if len(string):
if 'name' in self.temp:
self.temp['name'] = self.temp['name'] + string
else:
self.temp['name'] = string
if string != book_name:
self.temp = {}
#print string
elif self.is_subject_pub:
string = data.strip()
if len(string):
if 'pub' in self.temp:
self.temp['pub'] = self.temp['pub']+string
else:
self.temp['pub'] = string
elif self.is_subject_star:
string = data.strip()
if len(string) and self.is_subject_rating:
if 'star' in self.temp:
self.temp['star'] = self.temp['star'] + string
else:
self.temp['star'] = string
print string
else:
pass book_name = '现代操作系统'
douban_book = 'http://book.douban.com/subject_search?'
search = [('search_text','现代操作系统'),('cat','1001')]
getbook = douban_book + urllib.urlencode(search)
print getbook
content = urllib2.urlopen(getbook).read()
fobj = open('book.txt','w')
fileobj = open('books.txt','w')
book = BookInfo()
book.feed(content)
for books in book.info:
for item in books:
print '*************************************************'
print '书名:%s' % books['name']
if 'pub' in books:
print '出版信息:%s' % books['pub']
if 'star' in books:
print '评价:%s' % books['star']
break
fobj.write(content)
fobj.close()
fileobj.close()

下面是输出结果:

以后程序修改就是将这本书的所有版本的评价综合起来,在加上亚马逊的评价,就可以了。

-end-

Python学习 - 简单抓取页面的更多相关文章

  1. 003.[python学习] 简单抓取豆瓣网电影信息程序

    声明:本程序仅用于学习爬网页数据,不可用于其它用途. 本程序仍有很多不足之处,请读者不吝赐教. 依赖:本程序依赖BeautifulSoup4和lxml,如需正确运行,请先安装.下面是代码: #!/us ...

  2. [Python学习] 简单爬取CSDN下载资源信息

    这是一篇Python爬取CSDN下载资源信息的样例,主要是通过urllib2获取CSDN某个人全部资源的资源URL.资源名称.下载次数.分数等信息.写这篇文章的原因是我想获取自己的资源全部的评论信息. ...

  3. Python实现简单抓取功能

    一直以来都想好好学习Python,但是每次学习了从基础感觉学了一会就感觉没意思.今天学习一下爬虫,也算是自己学python的目的吧,但是在学习过程中遇到很多困难,但幸好遇到了一篇好博文,分享给大家:h ...

  4. Python抓取页面中超链接(URL)的三中方法比较(HTMLParser、pyquery、正则表达式) <转>

    Python抓取页面中超链接(URL)的3中方法比较(HTMLParser.pyquery.正则表达式) HTMLParser版: #!/usr/bin/python # -*- coding: UT ...

  5. 测试开发Python培训:抓取新浪微博抓取数据-技术篇

    测试开发Python培训:抓取新浪微博抓取数据-技术篇   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.在poptest的se ...

  6. 如何用 Python 实现 Web 抓取?

    [编者按]本文作者为 Blog Bowl 联合创始人 Shaumik Daityari,主要介绍 Web 抓取技术的基本实现原理和方法.文章系国内 ITOM 管理平台 OneAPM 编译呈现,以下为正 ...

  7. Python爬虫,抓取淘宝商品评论内容!

    作为一个资深吃货,网购各种零食是很频繁的,但是能否在浩瀚的商品库中找到合适的东西,就只能参考评论了!今天给大家分享用python做个抓取淘宝商品评论的小爬虫! 思路 我们就拿"德州扒鸡&qu ...

  8. Python爬虫实战---抓取图书馆借阅信息

    Python爬虫实战---抓取图书馆借阅信息 原创作品,引用请表明出处:Python爬虫实战---抓取图书馆借阅信息 前段时间在图书馆借了很多书,借得多了就容易忘记每本书的应还日期,老是担心自己会违约 ...

  9. 如何利用Python网络爬虫抓取微信好友数量以及微信好友的男女比例

    前几天给大家分享了利用Python网络爬虫抓取微信朋友圈的动态(上)和利用Python网络爬虫爬取微信朋友圈动态——附代码(下),并且对抓取到的数据进行了Python词云和wordart可视化,感兴趣 ...

随机推荐

  1. SourceTree的基本使用

    1. SourceTree是什么 拥有可视化界面的项目版本控制软件,适用于git项目管理 window.mac可用 2. 获取项目代码 1. 点击克隆/新建 2. 在弹出框中输入项目地址,http或者 ...

  2. asp.net redis 实战

    当开始用    var result=new RedisClient("127.0.0.1",6379,1"1111");  这个helper ,后面有并发之后 ...

  3. 推荐一个可视化的学习Git的好网站:LearnGitBranching

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:推荐一个可视化的学习Git的好网站:LearnGitBranching.

  4. mysql查询一天,查询一周,查询一个月的数据【转】

    转自:http://www.cnblogs.com/likwo/archive/2010/04/16/1713282.html 查询一天: select * from table where to_d ...

  5. 调试postgresql9.5.2最新源码

    最近在考量数据库的选型,考虑后期把数据切换到postgresql ,postgresql源码用c实现,代码很精炼完美,值得学习下 首先去pgsql官网下载最新的源码 ,然后还需要perl,bison ...

  6. Android项目svn代码管理问题[转]

    用svn控制版本,svn本身是不会识别哪些该传,哪些不该传,这就导致有些关于路径的东西(比如拓展jar的路径)也被上传了,而当别人下载后,那个路径对于这个人可能完全不存在,项目编译就会出问题.用ecl ...

  7. 2014年到期的myeclipse5.5.1注冊码

    假设点击Myeclipse的载入项目到server的图标没有反应,这就是MyEclipse过期了,下面是还能用一年的注冊码: subscriber: axin  Serial:nLR8ZC-85557 ...

  8. Android开发环境搭建(图文教程)

    昨天又搭建了一次Android的开发环境,尝试了好几种方式,也遇到了一些问题,在此分享一下. 注意:官网公布的最新版本号的SDK和ADT(23.0.0),对于和Eclipse集成的开发环境是有BUG存 ...

  9. SharePoint 2013 error The given assembly name or codebase System.ServiceModel.dll was invalid

    笔者近期在 SharePoint 2013 的环境中遇到一个奇怪的问题,前一天 SharePoint 2013 站点还是好好的.可是突然站点就报page can't display 500 错误: T ...

  10. 分享2D Unity游戏的动画制作经验

    作者:Alex Rose Unity近期宣布推出额外的2D游戏支持,加入了Box 2D物理和一个精灵管理器. 但这里还是有些技巧须要牢记在心.逐帧更改图像仅仅是动画制作的冰山一角,若要让你的游戏出色执 ...