Python爬虫-爬取糗事百科段子
闲来无事,学学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>包裹起来。我们点开其中一个,获取其中的用户名、段子内容和点赞数这三个信息。这三个信息分别用红、蓝、黑下划线圈起来。解析过程主要由正则表达式实现。
- 解析用户名。正则表达式为:<div class="author clearfix">.*?<h2>(.*?)</h2> 上图中用户名称为旖旎萌萌,处于<h2>和</h2>中间,用(.*?)代之。
- 解析段子内容。正则表达式为:<div.*?span>(.*?)</span> 同理,文字部分在<span>和</span>之间。<div .........span>之间的所有符号(含换行符)用.*?解决。
- 解析点赞数。正则表达式为:<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爬虫-爬取糗事百科段子的更多相关文章
- Python爬虫爬取糗事百科段子内容
参照网上的教程再做修改,抓取糗事百科段子(去除图片),详情见下面源码: #coding=utf-8#!/usr/bin/pythonimport urllibimport urllib2import ...
- python学习(十六)写爬虫爬取糗事百科段子
原文链接:爬取糗事百科段子 利用前面学到的文件.正则表达式.urllib的知识,综合运用,爬取糗事百科的段子先用urllib库获取糗事百科热帖第一页的数据.并打开文件进行保存,正好可以熟悉一下之前学过 ...
- Python爬虫--抓取糗事百科段子
今天使用python爬虫实现了自动抓取糗事百科的段子,因为糗事百科不需要登录,抓取比较简单.程序每按一次回车输出一条段子,代码参考了 http://cuiqingcai.com/990.html 但该 ...
- Python爬虫实战一之爬取糗事百科段子
大家好,前面入门已经说了那么多基础知识了,下面我们做几个实战项目来挑战一下吧.那么这次为大家带来,Python爬取糗事百科的小段子的例子. 首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把 ...
- 转 Python爬虫实战一之爬取糗事百科段子
静觅 » Python爬虫实战一之爬取糗事百科段子 首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把,这次我们尝试一下用爬虫把他们抓取下来. 友情提示 糗事百科在前一段时间进行了改版,导致 ...
- 8.Python爬虫实战一之爬取糗事百科段子
大家好,前面入门已经说了那么多基础知识了,下面我们做几个实战项目来挑战一下吧.那么这次为大家带来,Python爬取糗事百科的小段子的例子. 首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把 ...
- [爬虫]用python的requests模块爬取糗事百科段子
虽然Python的标准库中 urllib2 模块已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests 自称 “HTTP for Humans”,说明使用更 ...
- python爬取糗事百科段子
初步爬取糗事百科第一页段子(发布人,发布内容,好笑数和评论数) #-*-coding:utf--*- import urllib import urllib2 import re page = url ...
- 芝麻HTTP:Python爬虫实战之爬取糗事百科段子
首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把,这次我们尝试一下用爬虫把他们抓取下来. 友情提示 糗事百科在前一段时间进行了改版,导致之前的代码没法用了,会导致无法输出和CPU占用过高的 ...
随机推荐
- Apache的ProxyPass简单使用
转: Apache的ProxyPass简单使用 置顶 2017年08月14日 18:54:33 师太,老衲把持不住了 阅读数:11164 http://mtnt2008.iteye.com/blo ...
- eclipse复制工作空间配置
eclipse复制工作空间配置 eclipse复制工作空间配置 总结一下,复制工作空间配置步骤如下: 1 使用eclipse新建workspace. 2 将新建的workspace下的.metad ...
- BRIEF特征简介
引言 该文是由EPFL的Calonder在ECCV2010上提出了一种可以快速计算且表达方式为二进制编码的描述子.主要思路就是在特征点附近随机选取若干点对,将这些点对的灰度值的大小,组合成一个二进制串 ...
- 使用gdb+core查看错误信息
core的使用Linux下core文件调试方法 ulimit -c xxx可以设置core文件的大小 proc/sys/kernel/core_pattern可以控制core文件保存位置和文件名格式. ...
- pyglet and opengl -- 纹理映射以及动画
#-*- coding:gbk -*- #from pyglet.gl import * from OpenGL.GL import * import pyglet from pyglet impor ...
- JavaSE学习总结(六)——接口、抽象类、内部类
一.不需要实例化的原因 看一个示例: package com.zhangguo.chapter5.s1; /**动物园*/ public class Zoo { public static void ...
- 安装阿里云github提供的修改版minikube
由于kubenetes域名背墙(gcr.io),如kubernetes-dashboard服务依赖不能正常使用. $ docker pull gcr.io/google_containers/paus ...
- 【JUC】JDK1.8源码分析之CyclicBarrier
一.前言 有了前面分析的基础,现在,接着分析CyclicBarrier源码,CyclicBarrier类在进行多线程编程时使用很多,比如,你希望创建一组任务,它们并行执行工作,然后在进行下一个步骤之前 ...
- Codeforces 954 G. Castle Defense
http://codeforces.com/problemset/problem/954/G 二分答案 检验的时候,从前往后枚举,如果发现某个位置的防御力<二分的值,那么新加的位置肯定是越靠后越 ...
- delimiter 与 存储过程
1.如此执行语句不行,需要在 delimiter IF not EXISTS ( SELECT * FROM information_schema. COLUMNS WHERE table_schem ...