闲来无事,学学python爬虫。

在正式学爬虫前,简单学习了下HTML和CSS,了解了网页的基本结构后,更加快速入门。

1.获取糗事百科url

http://www.qiushibaike.com/hot/page/2/    末尾2指第2页

2.先抓取HTML页面

import urllib
import urllib2
import re
page = 2
url = 'http://www.qiushibaike.com/hot/page/' + str(page) #对应第2页的url
request = urllib2.Request(url) #发出申请
response = urllib2.urlopen(request) #收到回应

当然这里可能会产生error:主要有HTTPError和URLError。

产生URLError的原因可能是:

  • 网络无连接,即本机无法上网
  • 连接不到特定的服务器
  • 服务器不存在

异常捕获解决办法:

import urllib2

requset = urllib2.Request('http://www.xxxxx.com')
try:
urllib2.urlopen(request)
except urllib2.URLError, e:
print e.reason

HTTPError是URLError的子类,利用urlopen方法发出一个请求时,服务器上都会对应一个应答对象response,其中它包含一个数字”状态码”。举个例子,假如response是一个”重定向”,需定位到别的地址获取文档,urllib2将对此进行处理。常见的状态码:

200:请求成功      处理方式:获得响应的内容,进行处理

202:请求被接受,但处理尚未完成    处理方式:阻塞等待

204:服务器端已经实现了请求,但是没有返回新的信 息。如果客户是用户代理,则无须为此更新自身的文档视图。    处理方式:丢弃

404:没有找到     处理方式:丢弃

500:服务器内部错误  服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。一般来说,这个问题都会在服务器端的源代码出现错误时出现。

异常捕获解决办法:

import urllib2

req = urllib2.Request('http://blog.csdn.net/cqcre')
try:
urllib2.urlopen(req)
except urllib2.HTTPError, e:
print e.code
print e.reason

注:HTTPError是URLError的子类,在产生URLError时也会触发产生HTTPError。因此应该先处理HTTPError。上述代码可改写为:

import urllib2

req = urllib2.Request('http://blog.csdn.net/cqcre')
try:
urllib2.urlopen(req)
except urllib2.HTTPError, e:
print e.code
except urllib2.URLError, e:
print e.reason
else:
print "OK"

如果无法获得回应,可能需要加入header模拟浏览器发出请求:

import urllib
import urllib2 page = 1
url = 'http://www.qiushibaike.com/hot/page/' + str(page)
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
headers = { 'User-Agent' : user_agent }
try:
request = urllib2.Request(url,headers = headers) # 加入header
response = urllib2.urlopen(request)
print response.read()
except urllib2.URLError, e:
if hasattr(e,"code"):
print e.code
if hasattr(e,"reason"):
print e.reason

3.分析页面获取段子

如上图所示,划红对勾的是不同的段子,每个段子都由<div class="article block untagged mb15" id="...">...</div>包裹起来。我们点开其中一个,获取其中的用户名、段子内容和点赞数这三个信息。这三个信息分别用红、蓝、黑下划线圈起来。解析过程主要由正则表达式实现。

  1. 解析用户名。正则表达式为:<div class="author clearfix">.*?<h2>(.*?)</h2>   上图中用户名称为旖旎萌萌,处于<h2>和</h2>中间,用(.*?)代之。
  2. 解析段子内容。正则表达式为:<div.*?span>(.*?)</span>  同理,文字部分在<span>和</span>之间。<div .........span>之间的所有符号(含换行符)用.*?解决。
  3. 解析点赞数。正则表达式为:<div class="stats">.*?"number">(.*?)</i>  同理。用(.*?)代替1520。

正则表达式解释:(参考崔庆才博客

1).*? 是一个固定的搭配,.和*代表可以匹配任意无限多个字符,加上?表示使用非贪婪模式进行匹配,也就是我们会尽可能短地做匹配,以后我们还会大量用到 .*? 的搭配。

2)(.*?)代表一个分组,在这个正则表达式中我们匹配了五个分组,在后面的遍历item中,item[0]就代表第一个(.*?)所指代的内容,item[1]就代表第二个(.*?)所指代的内容,以此类推。

3)re.S 标志代表在匹配时为点任意匹配模式,点 . 也可以代表换行符。

content = response.read().decode('utf-8')
pattern = re.compile('<div class="author clearfix">.*?<h2>(.*?)</h2>.*?<div.*?span>(.*?)</span>.*?<div class="stats">.*?"number">(.*?)</i>',re.S)
items = re.findall(pattern,content) # 参考python中的re模块,作用是在content中寻找可以匹配pattern的串,即段子

但是有个问题,上面的表达式将有图和无图的段子都爬取下来了,但是在图片一般不会显示,所以需要去掉有图的段子,只爬取无图片的段子。需要稍微改动正则表达式。

上图是无图的段子html代码,下图是有图的段子的html代码:

红线划的<div class="thumb">包含了图片部分,而这条语句在无图段子的html中是不存在的,所以利用这条语句中的“img”(上图下划线)来过滤段子。同时注意到这条语句处在段子内容和点赞数中间。

所以在段子内容和点赞这两个正则语句之间加上一个(.*?)即可,这样一来,只要检测到包括“img”,就过滤掉。

content = response.read().decode('utf-8')
pattern = re.compile('<div class="author clearfix">.*?<h2>(.*?)</h2>.*?<div.*?span>(.*?)</span>(.*?)<div class="stats">.*?"number">(.*?)</i>' # 注意这个(.*?)
,re.S)
items = re.findall(pattern,content) # items就是根据正则表达式筛选到的字符串(html串)
for item in items:
haveImg = re.search("img", item[2]) # 0,1,2,3分别表示用户名,段子内容,图片,点赞数。所以用item[2]来检测过滤
if not haveImg:
print item[0], item[1], item[3]

好,以上代码就是可以实现将一页中的无图段子全部爬取出来:代码:

import urllib
import urllib2
import re
page = 2
url = 'http://www.qiushibaike.com/hot/page/' + str(page)
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
headers = {'User-Agent':user_agent}
request = urllib2.Request(url, headers=headers)
response = urllib2.urlopen(request)
content = response.read().decode('utf-8')
pattern = re.compile('<div class="author clearfix">.*?<h2>(.*?)</h2>.*?<div.*?span>(.*?)</span>(.*?)<div class="stats">.*?"number">(.*?)</i>'
,re.S)
items = re.findall(pattern,content)
for item in items:
haveImg = re.search("img", item[2])
if not haveImg:
print item[0], item[1], item[3]

4.以上代码是核心,但是略有简陋,稍加修补:

# coding:utf-8

import urllib
import urllib2
import re class Spider_QSBK:
def __init__(self):
self.page_index = 2
self.enable = False
self.stories = []
self.user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
self.headers = {'User-Agent':self.user_agent} def getPage(self, page_index):
url = 'http://www.qiushibaike.com/hot/page/' + str(page_index)
try:
request = urllib2.Request(url, headers=self.headers)
response = urllib2.urlopen(request)
content = response.read().decode('utf-8')
return content
except urllib2.URLError, e:
print e.reason
return None def getStories(self,page_index):
content = self.getPage(page_index)
pattern = re.compile('<div class="author clearfix">.*?<h2>(.*?)</h2>.*?<div.*?span>(.*?)</span>(.*?)<div class="stats">.*?"number">(.*?)</i>'
,re.S)
items = re.findall(pattern,content)
for item in items:
haveImg = re.search("img", item[2])
if not haveImg:
self.stories.append([item[0], item[1], item[3]])
return self.stories def ShowStories(self, page_index):
self.getStories(page_index)
for st in self.stories:
print u"第%d页\t发布人:%s\t点赞数:%s\n%s" %(page_index, st[0], st[2], st[1])
del self.stories def start(self):
self.enable = True
# while self.enable:
self.ShowStories(self.page_index)
self.page_index += 1 spider = Spider_QSBK()
spider.start()

结果一样:

Python爬虫-爬取糗事百科段子的更多相关文章

  1. Python爬虫爬取糗事百科段子内容

    参照网上的教程再做修改,抓取糗事百科段子(去除图片),详情见下面源码: #coding=utf-8#!/usr/bin/pythonimport urllibimport urllib2import ...

  2. python学习(十六)写爬虫爬取糗事百科段子

    原文链接:爬取糗事百科段子 利用前面学到的文件.正则表达式.urllib的知识,综合运用,爬取糗事百科的段子先用urllib库获取糗事百科热帖第一页的数据.并打开文件进行保存,正好可以熟悉一下之前学过 ...

  3. Python爬虫--抓取糗事百科段子

    今天使用python爬虫实现了自动抓取糗事百科的段子,因为糗事百科不需要登录,抓取比较简单.程序每按一次回车输出一条段子,代码参考了 http://cuiqingcai.com/990.html 但该 ...

  4. Python爬虫实战一之爬取糗事百科段子

    大家好,前面入门已经说了那么多基础知识了,下面我们做几个实战项目来挑战一下吧.那么这次为大家带来,Python爬取糗事百科的小段子的例子. 首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把 ...

  5. 转 Python爬虫实战一之爬取糗事百科段子

    静觅 » Python爬虫实战一之爬取糗事百科段子 首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把,这次我们尝试一下用爬虫把他们抓取下来. 友情提示 糗事百科在前一段时间进行了改版,导致 ...

  6. 8.Python爬虫实战一之爬取糗事百科段子

    大家好,前面入门已经说了那么多基础知识了,下面我们做几个实战项目来挑战一下吧.那么这次为大家带来,Python爬取糗事百科的小段子的例子. 首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把 ...

  7. [爬虫]用python的requests模块爬取糗事百科段子

    虽然Python的标准库中 urllib2 模块已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests 自称 “HTTP for Humans”,说明使用更 ...

  8. python爬取糗事百科段子

    初步爬取糗事百科第一页段子(发布人,发布内容,好笑数和评论数) #-*-coding:utf--*- import urllib import urllib2 import re page = url ...

  9. 芝麻HTTP:Python爬虫实战之爬取糗事百科段子

    首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把,这次我们尝试一下用爬虫把他们抓取下来. 友情提示 糗事百科在前一段时间进行了改版,导致之前的代码没法用了,会导致无法输出和CPU占用过高的 ...

随机推荐

  1. php动态获取常量

    class A1{ const V1='100'; const V2='200'; const V3='Hello world'; } $v1 = 'V3'; $a1 = constant('A1:: ...

  2. 用树莓派改装电风扇及实现Android遥控

    最近天气很热,我租的房子又没有空调,基本上风扇一开就是一晚上,结果经常起床后发现口干舌燥的.我觉得这肯定是因为整晚吹风扇搞的,不管是不是,反正我觉得就是了.不开风扇吧,热!开风扇吧,早上起来不舒服,怎 ...

  3. Hdoj 基本输入输出8道(1089-1096)

    Hdoj 1089 #include<bits/stdc++.h> using namespace std; int main() { int a,b; while(cin>> ...

  4. 前端学习 -- Html&Css -- 条件Hack 和属性Hack

    条件Hack 语法: <!--[if <keywords>? IE <version>?]> HTML代码块 <![endif]--> <keyw ...

  5. 斯坦福大学公开课机器学习:Neural network-model representation(神经网络模型及神经单元的理解)

    神经网络是在模仿大脑中的神经元或者神经网络时发明的.因此,要解释如何表示模型假设,我们先来看单个神经元在大脑中是什么样的.如下图,我们的大脑中充满了神经元,神经元是大脑中的细胞,其中有两点值得我们注意 ...

  6. idea 显示properties 中文

    有时我们打开.properties文件时,中文显示为utf8编码格式,可以在file->setting->editor->file encodings下 把transparent n ...

  7. vs widows服务的开发

    最近再做一个视频管理系统,发现用户提交时实时转换视频非常慢.于是有了通过建立一个单独的服务.通过服务定时查询数据库,是否有需要转换的视频来解决问题.现把过程记录下来,已供参考 1.新建widows 服 ...

  8. 过时date.toLocaleString()的解决方法

    System.out.println(new java.util.Date()); 输出:Thu Jan 27 14:43:28 CST 2011 System.out.println(new jav ...

  9. linux tail -f messages查看控制台失败

    [root@localhost log]# tail -f /var/log/messages ......................... tail: cannot watch `/var/l ...

  10. python---redis缓存页面实现

    import tornado.web from controllers.BaseController import BaseRequestHandler import redis pool = red ...