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可视化,感兴趣 ...
随机推荐
- 当可以设置src时,不必发ajax请求,如果没有参数设置src即可
var params = (function(obj){ var string = []; for(var key in obj){ string.push(window.encodeURI(key) ...
- 推荐一个可以直接在Visual Studio中看到complexity的插件CodeMaid
博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:推荐一个可以直接在Visual Studio中看到complexity的插件CodeMaid.
- mysql技术调优资料整理
1,15 个有用的 MySQL/MariaDB 性能调整和优化技巧 2,MariaDB设置主从复制 3,CentOS6.4安装mysql2redis http://www.cnblogs ...
- 通过GWT RPC实现客户端与服务器端的交互
GWT有两种与服务端进行交互的技术:GWT RPC和基于普通AJAX的远程交互技术.这里只介绍GWT RPC技术. 一个完整的RPC服务至少包含三个Java文件: 1.客户端远程接口类,需要继承Rem ...
- emacs配置详解及C/C++IDE全功能配置演示(附配置文件)
我的emacs插件下载地址: http://pan.baidu.com/share/link?shareid=4196458904&uk=3708780105 说明: 1.为什么使用emacs ...
- 使用Java程序发送Email
目前很多大型的网站忘记登录密码常见的一种形式是使用邮箱找回密码 最近做项目也有这个需求 现在总结一下 以便以后查看 使用到的包有 mailapi.jar smtp.jar 封装发送邮 ...
- java 加减乘除错误
有次做一个for循环(1000次左右),做的事情也是很简单的事情,就是 Double testValue = (long类型 / 8 ) * long类型 的一些加减乘除操作, 但是总是出现一些数 ...
- mybatis06 增删改差 源码
user.java package cn.itcast.mybatis.po; import java.util.Date; public class User { private int id; p ...
- linux下so动态库一些不为人知的秘密 系列
http://blog.chinaunix.net/uid-27105712-id-3313293.html http://www.cnblogs.com/gulvzhe/archive/2012/0 ...
- PureMVC(JS版)源码解析(九):View类
在讲解View类之前,我们先回顾一下PureMVC的模块划分: 在PureMVC中M.V.C三部分由三个单例类管理,分别是Model/View/Controller.PureMVC中另外一个 ...