python实现一个简单的爬虫

今天第一次写爬虫,感觉非常有趣!,中途也遇到了许多问题,所以写篇博客~

目标:爬取豆瓣编程类书籍中9分以上的

刚接触爬虫,说下我的认识(不一定准确^_^)

我们知道网页的呈现也是用编程语言写出来的,有源码,每个网页我们都可以查看它的源码,我的浏览器快捷键是Ctrl+U,

一般点击右键就可以看见查看源码。因为要爬取豆瓣的数据,那看看下图豆瓣图书页面的部分源码

它所对应的数据是这样的

那么我们知道了,网页上所能看见的每个数据在源码上都能找到,有的点击会跳转也是因为源码上链接着其他地方。

所以我们直接分析源码即可。

思路

其实很简单,我们想要爬取编程类9分以上的书籍。那么从编程类的首页开始爬取数据。

用正则表达式来过滤数据,取出9分以上的数据,关于正则表达式如果不熟悉可参考我的上篇文章^_^

然后我们在每个网页的最后可以发现跳转到下一个网页的链接,通过正则表达式过滤出这个链接即可。

保存这个链接作为下一次爬取的url。

我设置的结束条件是爬取当前页的9分以上书籍为0时跳出循环,为了简单起见。

看代码:

#!/usr/bin/env python
#coding:UTF-8

import urllib
import re

#得到一个网页的源码
def gethtml(url):
    #返回类似文件描述副,可进行读操作,read返回str
    page = urllib.urlopen(url)
    html = page.read()
    return html

#根据正则得到我们想要的数据
def getdata(obj):
    patt = r'(<dl>.+?>(9\.\d).+?</dl>)'
    #编译正则模块
    pattern = re.compile(patt, re.DOTALL)
    #findall查询此页面所有符合条件的数据,返回list
    m = pattern.findall(obj)
    Len = len(m)
    print 'len: %d' % Len
    if m is not None:
        for i in m:
            print i[1],
        print
    else:
        print 'not found'
    #如果此页面的9分数据为0,则认为没有9分数据
    if Len == 0:
        return False
    else:
        return True

#得到下一个页面
def getnextpage(obj):
    #我们要爬去的每个页面url前面都一样,所以只换后面的数据即可
    nextpage = 'http://www.douban.com/tag/%E7%BC%96%E7%A8%8B/book?start='
    #根据正则匹配后面的数据,然后连接到一起
    patt = '<span class="break">...</span>.+start=(\d+)'
    pattern = re.compile(patt, re.DOTALL)
    #下一个页面只有一个符合数据,所以用search
    m = pattern.search(obj)
    if m is not None:
        nextpage += m.group(1)
    else:
        print 'not found'
    return nextpage

if __name__ == '__main__':
    #起始页面
    html = gethtml("http://www.douban.com/tag/%E7%BC%96%E7%A8%8B/book")

    while 1:
        if getdata(html) == False:
            break
        ret = getnextpage(html)
        html = gethtml(ret)

注释写的比较详细。运行结果我输出了每个页面的书籍分数,len是此页面9分以上书籍的数量

运行结果:部分数据

遇到的问题:貌似都是正则表达式的问题 - - 。

1.

网页源码中每个书籍是这样的

可以看见我们要分析的数据中间包含中文,过滤中文首先必须要在开头加上

#coding:UTF-8,‘  .  ‘符号在正则中可以过滤任何字符,\w只能是字母和数字

其次这段数据中包含了许多换行符号,在正则表达式中\s只能过滤空白字符,不能过滤回车。

我们需要在

    #编译正则模块
    pattern = re.compile(patt, re.DOTALL)

里面设则,DOTALL的意思就是忽略回车符号

2.findall的问题

findall是正则匹配中一次匹配多个数据的函数

它返回的是一个list。

先来看看遇到的问题吧

在getdata中,我的需求是获取每本书的整个标签,也就是上面的图片,但是我还想顺便过滤出分数,就是把分数也作为一个分组可以查看。

类似m = search.( ),m.group(0),m.group(1)。

但是findall返回的是list,里面的数据是str。

和小伙伴讨论后又仔细了书,结论:

当正则表达式只有一个子组的时候(()是一个子组),findall( )返回子组匹配的字符串组成的列表,如果表达式有多个子组,返回的是一个元组的列表

元组中的每个元素都是一个子组的匹配内容,像这样的元组构成了返回列表中的元素

这也是为什么代码中我用的是m[1],因为返回的是一个元组呗!

顺便吐槽下python核心编程这本书,我目前发现的印刷错误至少十几处了!

而且findall( )这部分除了简单的介绍外没有给任何例子,结尾还说了句 “这些内容初次听到可能感到费解,但如果你看看各种例子,就会明白了”

它没给例子...

3.贪婪匹配

很重要,当时我只是简单的看了看,没太在意,结果实战就出错了

原本我的getdata正则是这样写的

def getdata(obj):
    patt = r'(<dl>.+>(9\.\d).+</dl>)'

怎么匹配也出不来

于是发现了贪婪匹配的问题

正则表达式默认是贪心匹配的,简单来说,如果正则表达式用到通配符(*, +, ?)等,它在从左到右匹配的时候会尽量匹配

最长的字符串。

看个例子:

#!/usr/bin/env python
#coding:UTF-8

import re

s = 'helloworld800-333-3333'
patt = '.+(\d+-\d+-\d+)'

m = re.search(patt, s)
print m.group(1)

我们想得出结果800-333-3333这个号码

结果却是

因为patt前面的‘.+‘默认是贪婪匹配的,它会匹配它能匹配尽量多的字符,所以我们后面的\d+只能匹配了一个0而已

解决办法是用非贪婪操作符号 ‘ ? ‘

那么‘.+‘就不会尽量读取多的字符

patt = '.+?(\d+-\d+-\d+)'

可以运行下试试,结果为800-333-3333

正则表达式问题的却比较多,一个学长建议我用BeautifulSoup来解析,会方便很多,感兴趣可以试试。

简单的入门,见笑了 ^_^

时间: 2024-10-12 20:45:01

python实现一个简单的爬虫的相关文章

Python写一个简单的爬虫

code #!/usr/bin/env python # -*- coding: utf-8 -*- import requests from lxml import etree class Main: def __init__(self): self.headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69

python实现一个简单的爬虫搜索功能

html.parser HTMLParser   urllib.request urlopen   urllib parse LinkParser(HTMLParser):     handle_starttag(, tag, attrs):         tag == :             (key, value) attrs:                 key == :                     newUrl = parse.urljoin(.baseUrl, v

python 一个简单的爬虫(1)

1.一个简单的爬虫:爬取豆瓣的热门电影的信息 技能:获取网页源码,正则表达式,函数调用,全局变量的定义 1 #! /usr/bin/env python 2 # -*- coding=utf-8 -*- 3 import requests 4 import json 5 import re 6 import sys 7 reload(sys) 8 sys.setdefaultencoding("utf-8") 9 classinfo = [] 10 f = open('info.txt

$python爬虫系列(1)——一个简单的爬虫实例

本文主要实现一个简单的爬虫,目的是从一个百度贴吧页面下载图片. 1. 概述 本文主要实现一个简单的爬虫,目的是从一个百度贴吧页面下载图片.下载图片的步骤如下: 获取网页html文本内容: 分析html中图片的html标签特征,用正则解析出所有的图片url链接列表: 根据图片的url链接列表将图片下载到本地文件夹中. 2. urllib+re实现 #!/usr/bin/python # coding:utf-8 # 实现一个简单的爬虫,爬取百度贴吧图片 import urllib import r

python中一个简单的webserver

python中一个简单的webserver 2013-02-24 15:37:49 分类: Python/Ruby 支持多线程的webserver 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #!/usr/bin/python from SocketServer import ThreadingMixIn from BaseHTTPServer import HTTPServer,BaseHTTPRequestHandler cla

【Python】一个简单的例子

问题描述: Python基础篇 参考资料: (1)http://www.cnblogs.com/octobershiner/archive/2012/12/04/2801670.html (2)http://www.cnblogs.com/itech/archive/2010/06/20/1760345.html 例子: 求解Fibonacci glb_var.py gl_count=1 path.py # coding:utf-8 ''' Created on 2014-4-28 @autho

【译】使用python创建一个简单的restful风格的webservice应用

这是一个如何使用python快速构建简单restful风格webservice的应用教程. 1.分析rest路由规则 rest风格的服务通常使用web.py来创建服务器端脚本,一般情况下包含两个url路径: 一个是为了查询所有用户,一个是为了查询单个用户. 例如下面的url: http://localhost:8080/users http://localhost:8080/users/{id} 2.搭建web.py环境 首先你应该安装web.py模块到你的python环境下.如果你之前没有的话

一个简单网络爬虫示例(转载)

在学生时期,可能听到网络爬虫这个词会觉得很高大上,但是它的简单实现可能学生都不难懂. 网络爬虫应用,就是把整个互联网真的就当做一张网,像蜘蛛网那样,应用就像一个虫子,在网上面按照一定的规则爬动. 现在互联网应用最广的就是http(s)协议了,本文例子就是基于使用http(s)协议的,只作为示例,不涉及复杂的算法(实际上是最重要的). 设计思路: 程序入口从一个或多个url开始,通过http(s)获取url的内容,对获取到内容处理,获取内容中需要爬取的信息,获取到内容中的url链接,再重复以上步骤

【龙书笔记】用Python实现一个简单数学表达式从中缀到后缀语法的翻译器(采用递归下降分析法)

上篇笔记介绍了语法分析相关的一些基础概念,本篇笔记根据龙书第2.5节的内容实现一个针对简单表达式的后缀式语法翻译器Demo. 备注:原书中的demo是java实例,我给出的将是逻辑一致的Python版本的实现. 在简单后缀翻译器代码实现之前,还需要介绍几个基本概念. 1. 自顶向下分析法(top-down parsing) 顾名思义,top-down分析法的思路是推导产生式时,以产生式开始符号作为root节点,从上至下依次构建其子节点,最终构造出语法分析树.在具体实现时,它会把输入字符串从左到右