闲来无事,学学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占用过高的 ...
随机推荐
-
Android第一天
---恢复内容开始--- 一.配置JDK 第一步:右键我的电脑-属性-高级系统设置-环境变量 输入变量名和变量值: 环境变量名和变量值: 变量名:JAVA_HOME 变量值:D:\Java\jdk1. ...
-
MongoDB修改器总结
1"$set":用来制定一个字段值,若不存在,则创建: 一般用于点加一个字段 db.users.update({name:"joe"},{" ...
-
jelq
初级 The Newbie Routine 5 minutes hot wrap 5 minutes manual stretch (ten 30-second stretches) 10 minut ...
-
WinForm给控件加入hint文字
本文代码主要是参考别人的,仅为个人记录,方面后续使用~ 效果图: 主要代码在一个Win32Utility类中,代码如下: public static class Win32Utility { [Dll ...
-
Android编程: fragment组件、菜单和Intent组件
学习内容:fragment组件.菜单和Intent组件 ====fragment组件====1.fragment是一种自我容纳,模块化的,嵌入在一个Activity里面的视图组件 可以在运行时动 ...
-
Python学习 之 文件
1.文件读写 python进行文件读写的函数是open或file file_handler=open(filename,,mode) (1)打开并读取文件 方式一:open() fo=open('/r ...
-
MYSQL while 、repeat
前期准备: createt table employee(ID int ,Name varchar(4)); 用下列方法向表中循环插入数据. ----------------------------- ...
-
BZOJ 2440 完全平方数(莫比乌斯反演+二分查找)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=23362 题意:定义含有平方数因子的数为完全平方数(平方数因子不包含 ...
-
OpenCppCoverage 的使用
OpenCppCoverage 的使用 OpenCppCoverage 是一款好用方便的 C++ 代码覆盖率检测工具,可以独立在命令行运行也可以作为 Visual Studio 13/15/17 的插 ...
-
Laravel技巧之记录多日志
相信每个小伙伴在使用laravel的时候都会记录日志.查看日志.那么问题来了,比如我在对接zabbix接口的时候,使用 Log::info() 会让日志全部记录在 storage/logs/larav ...