Python学习 - 简单抓取页面
最近想做一个小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文本
- 第一步,利用浏览器自带的查看页面信息的工具,查看页面布局。

- 根据布局,思考解析的方法。这一步很主要,决定了第三步的效率
- 编写代码。基本上就是重写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学习 - 简单抓取页面的更多相关文章
- 003.[python学习] 简单抓取豆瓣网电影信息程序
声明:本程序仅用于学习爬网页数据,不可用于其它用途. 本程序仍有很多不足之处,请读者不吝赐教. 依赖:本程序依赖BeautifulSoup4和lxml,如需正确运行,请先安装.下面是代码: #!/us ...
- [Python学习] 简单爬取CSDN下载资源信息
这是一篇Python爬取CSDN下载资源信息的样例,主要是通过urllib2获取CSDN某个人全部资源的资源URL.资源名称.下载次数.分数等信息.写这篇文章的原因是我想获取自己的资源全部的评论信息. ...
- Python实现简单抓取功能
一直以来都想好好学习Python,但是每次学习了从基础感觉学了一会就感觉没意思.今天学习一下爬虫,也算是自己学python的目的吧,但是在学习过程中遇到很多困难,但幸好遇到了一篇好博文,分享给大家:h ...
- Python抓取页面中超链接(URL)的三中方法比较(HTMLParser、pyquery、正则表达式) <转>
Python抓取页面中超链接(URL)的3中方法比较(HTMLParser.pyquery.正则表达式) HTMLParser版: #!/usr/bin/python # -*- coding: UT ...
- 测试开发Python培训:抓取新浪微博抓取数据-技术篇
测试开发Python培训:抓取新浪微博抓取数据-技术篇 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.在poptest的se ...
- 如何用 Python 实现 Web 抓取?
[编者按]本文作者为 Blog Bowl 联合创始人 Shaumik Daityari,主要介绍 Web 抓取技术的基本实现原理和方法.文章系国内 ITOM 管理平台 OneAPM 编译呈现,以下为正 ...
- Python爬虫,抓取淘宝商品评论内容!
作为一个资深吃货,网购各种零食是很频繁的,但是能否在浩瀚的商品库中找到合适的东西,就只能参考评论了!今天给大家分享用python做个抓取淘宝商品评论的小爬虫! 思路 我们就拿"德州扒鸡&qu ...
- Python爬虫实战---抓取图书馆借阅信息
Python爬虫实战---抓取图书馆借阅信息 原创作品,引用请表明出处:Python爬虫实战---抓取图书馆借阅信息 前段时间在图书馆借了很多书,借得多了就容易忘记每本书的应还日期,老是担心自己会违约 ...
- 如何利用Python网络爬虫抓取微信好友数量以及微信好友的男女比例
前几天给大家分享了利用Python网络爬虫抓取微信朋友圈的动态(上)和利用Python网络爬虫爬取微信朋友圈动态——附代码(下),并且对抓取到的数据进行了Python词云和wordart可视化,感兴趣 ...
随机推荐
- 360浏览器拦截弹窗,window.open方式打不开新页面
window.open虽然在很多时候被广大中小站长用于弹窗广告的展示,所以广受争议,但是在业务需求中还是有很多场景需要用到此功能.然而,大多数浏览器对此都有一定的安全策略进行阻止,为此本文将针对以下浏 ...
- Sublime_text3怎么运行php代码
开发神奇sublime写代码真的好爽,之前听说是神器,但是没去用,觉得用eclipse写php代码,用dw写html够用了,用了一下sublime,哈哈,爽爆了. 除了写前端代码外,还需要写php代码 ...
- SDK更新太慢
同时,更新ADT和SDK Manager 在SDK Manager下Tools->Options打开了SDK Manager的Settings,选中“Force https://… source ...
- Cocos2d-js 3.0 alp2 使用指南
Download Cocos2d-JS: http://www.cocos2d-x.org/download Unzip and copy to C:/ Download JDK: http://ww ...
- ADO.NET与Oracle(一):获取多行记录集
近期接触ADO.NET和Oracle.将我寻常遇到的一些问题和大家共享. 我认为要想入门ADO.NET操作Oracle,最主要的要求就是要会通过ADO.NET更新Oracle中的数据. 该文简单讲些利 ...
- Btrace是一个实时监控工具
http://blog.csdn.net/gzh0222/article/details/9731031 Btrace是一个实时监控工具,可以无需修改应用代码(事实上它修改了字节码),来达到不可告人的 ...
- LabVIEW系列——生产现场故障邮件通知
第一步.建立邮件服务器,winmail做邮件服务器是个不错的选择.不过在使用前需要注册. 第二步.创建修改域名.这里创建的域名不是真正的域名,只能用于局域网内.假设:lhy.com.cn 第三步.创建 ...
- 使用lua给wireshark编写uTP的Dissector
lonelycastle做uTP的实验,使用wireshark捕包,但是最初没有找到wireshark下的uTP的dissector,每次都需要比对文档,这样做实验理解报文含义,效率非常低.作为程 ...
- 【NodeJs】Ctrl+C在Linux平台和Windows平台下的TCP连接中的不同表现
Linux平台:CentOS release 6.5 (Final) Windows平台:Windows 7 旗舰版 服务器端代码如下: var net = require('net'); var s ...
- WTL的消息机制
Windows消息 众所周知,Windows消息有两种:队列话消息和非队列话消息.队列话消息是被Windows操作系统放入消息队列的,程序通过主消息循环不断的从消息队列中取出消息并分发到各自的窗体调用 ...