闲来无事,学学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. LOJ #2434. 「ZJOI2018」历史(LCT)

    题意 click here 题解 我们首先考虑答案是个什么样的东西, 不难 发现每个点可以单独计算它的贡献. 令每个点 \(i\) 崛起次数为 \(a_i\) . 假设一个点子树的 \(\sum a_ ...

  2. BZOJ 4004 [JLOI2015]装备购买 | 线性基

    题目链接 Luogu P3265 题解 非常正常的线性基! 但是我不会线性基-- (吐槽:#define double long double 才过--) #include <cstdio> ...

  3. 洛谷 P1053 音乐会的等待 解题报告

    P1823 音乐会的等待 题目描述 \(N\)个人正在排队进入一个音乐会.人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人.队列中任意两个人\(A\)和\(B\),如果他们是相邻或他们之 ...

  4. hdu3072 Intelligence System (最小树形图?)

    题意:给一个有向图,问要从0号点能到达所有点所需要经过路径的最小权值和是多少,然而,若两点强联通,则这两点互相到达不需要花费.保证0号点能到达所有点 tarjan缩点以后直接取每个点入边中花费最小的即 ...

  5. 【uoj336】【清华集训2017】无限之环

    题目 描述 ​ 给出一个\(n*m\)的网格,每个格子里的水管可能向四个方向都有接口: ​ 游戏的目的是不能让水管漏水,即所有接口都有另一个接口与之相接: ​ 你一步可以将一个格子中的水管旋转\(90 ...

  6. C# 面向对象的封装、继承、多态

    一.封装: 封装:把客观的事物封装成类,使用和修改方便: 作用和结构体使用方法相似,程序执行流程不同: 要点:成员变量,属性,成员方法,构造函数,成员方法的静态和非静态,命名空间,常用的访问修饰符pu ...

  7. Codeforces Round #514 (Div. 2) D. Nature Reserve

    http://codeforces.com/contest/1059/problem/D 最大值: 最左下方和最右下方分别有一个点 r^2 - (r-1)^2 = (10^7)^2 maxr<0 ...

  8. NOIP 普及组 2014 珠心算测验

    传送门 https://www.cnblogs.com/violet-acmer/p/9898636.html 题解: 枚举两两间出所有的可能加和,然后遍历一遍这 n 个数,找出满足条件的总个数. 这 ...

  9. 一次完整的 HTTP 请求过程

    一次完整的HTTP请求过程从TCP三次握手建立连接成功后开始,客户端按照指定的格式开始向服务端发送HTTP请求,服务端接收请求后,解析HTTP请求,处理完业务逻辑,最后返回一个HTTP的响应给客户端, ...

  10. 第1课:SQL注入原理深度解析

    对于Web应用来说,注射式攻击由来已久,攻击方式也五花八门,常见的攻击方式有SQL注射.命令注射以及新近才出现的XPath注射等等.本文将以SQL注射为例,在源码级对其攻击原理进行深入的讲解. 一.注 ...