最近想做一个小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. hbulider 快捷键以及常用

    跳转到行        Ctrl + G   页首        Ctrl + Home   页尾        Ctrl + End   下一个选项卡        Ctrl + Tab   上一个 ...

  2. jquery.qrcode.min.js生成二维码 通过前端实现二维码生成

    主体代码: <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <tit ...

  3. Hrbust1328 相等的最小公倍数 (筛素数,素因子分解)

    本文出自:http://blog.csdn.net/svitter/ 题意: 求解An 与 An-1是否相等. n分为两个情况-- 1.n为素数, 2.n为合数. =  =好像说了个废话..素数的时候 ...

  4. mybatis06 增删改差 源码

    user.java package cn.itcast.mybatis.po; import java.util.Date; public class User { private int id; p ...

  5. JAVA格式化时间日期

    JAVA格式化时间日期 import java.util.Date; import java.text.DateFormat; /** * 格式化时间类 * DateFormat.FULL = 0 * ...

  6. Servlet中文乱码解决方法

    程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件. 字节流和字符流的区别: 在Java.io包中操作文件内容的主要有两大类:字节流.字符流,两类都分为输入和输出操作. 在字节流中输 ...

  7. Android自定义DataTimePicker(日期选择器)

    实现的效果就是在同一个布局上显示日期选择和时间选择,时间不准确bug修复 1.自定义类DateTimePickDialogUtil.java public class DateTimePickDial ...

  8. CentOS7系统下搭建Jenkins环境

    1. 安装JDK yum -y install java 2.安装Ant 添加JPackage源 yum -y install wget wget http://www.jpackage.org/jp ...

  9. CentOS 6.7配置Nginx 1.8负载均衡

    本教程使用Vultr的VPS搭建,准备三台VPS,一主两从 master - 45.32.90.100 slave1 - 45.32.92.47 slave2 - 45.32.89.205 1.编译安 ...

  10. return与finally

    当return遇到了finally,先标记return的值,然后执行finally,当finally修改了return的值,那么执行finally后,传递最后一次return的值,若finally没有 ...