Python爬虫教程——实用爬虫百科全书
大家好,前面已经讲了这么多基础知识了。 现在我们来做几个实际的项目来挑战一下。 那么这次我就给大家带来一个《尴尬事百科》中爬行小笑话的例子。
首先,大家都听说过《尴尬故事百科全书》吧? 尴尬的朋友发布了很多有趣的笑话。 这次我们尝试使用爬虫来捕获它们。
温馨的提示
前段时间尴尬事百科进行了修改,导致之前的代码变得无法使用,导致无法输出,CPU占用过高。 这是因为正则表达式不匹配。
现在,博主重新修改了程序,代码可供个人测试,包括截图和说明。 之前比较忙,没有及时更新。 希望大家能够理解!
更新时间:2015/8/2
本文的目标
1. 从《尴尬事百科全书》中获取流行笑话
2.用图片过滤笑话
3、每次按回车键,会显示笑话的发布时间、发布者、内容、点赞数。
尴尬事百科不需要登录,所以没必要使用。 另外,《尴尬事百科》中的一些笑话还配有图片。 如果我们截取了图片,而图片不容易展示,那么我们就会尝试过滤掉带有图片的笑话。
好吧,现在让我们尝试从尴尬故事百科全书中获取流行的笑话。 每次按 Enter 时,我们都会显示一个笑话。
1.确定URL并抓取页面代码
首先,我们确定页面的URL,其中最后一个数字1代表页码。 我们可以传入不同的值来获取某个页面的段落内容。
我们首先构建以下代码来尝试打印页面代码内容。 首先我们构造一个最基本的页面抓取方法,看看是否会成功。
\# -*- coding:utf-8 -*-
import urllib
import urllib2
page = 1
url = 'http://www.qiushibaike.com/hot/page/' + str(page)
try:
request = urllib2.Request(url)
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
运行程序,哦不,居然报错了。 实在是运气和命运都不好。
line 373, in _read_status
raise BadStatusLine(line)
httplib.BadStatusLine: ''
嗯,应该是验证问题。 让我们通过添加验证来尝试一下。 修改代码如下
\# -*- coding:utf-8 -*-
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)
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
呵呵,这次终于正常运行了,第一页的HTML代码打印出来了。 您可以运行代码并尝试一下。 这里的运行结果太长所以我不会发布它们。
2.提取某一页面的所有段落
好了,获取到HTML代码之后,我们就开始分析如何获取某个页面的所有段落。
首先,让我们检查一下元素并在浏览器上按 F12。 截图如下:
我们可以看到,每一个笑话都是
content = response.read().decode('utf-8')
pattern = re.compile('<div.*?author">.*?<a.*?<img.*?>(.*?)a>.*?<div.*?'+
'content">(.*?).*?div>(.*?)<div class="stats.*?class="number">(.*?)i>',re.S)
items = re.findall(pattern,content)
for item in items:
print item[0],item[1],item[2],item[3],item[4]
现在这里稍微解释一下正则表达式
1. ? 是一个固定的组合, . 并意味着它可以匹配任意数量的字符,加上 ? 表示使用非贪婪模式进行匹配,即我们会让匹配尽可能短,并且我们会使用大量的.*? 未来的组合。
2. (.?) 代表一个组。 在此正则表达式中,我们匹配五个组。 在后续的item遍历中,item[0]代表第一个(.?)指向的内容,item[1]代表第二个(.*?)指向的内容,以此类推。
3、re.S标志表示匹配时dot的任何匹配模式,以及dot。 也可以表示换行符。
这样我们就得到了发布者、发布时间、发布内容、附图和点赞数。
这里注意一下,如果我们要获取的内容有图片的话,直接输出会比较麻烦,所以这里我们只获取没有图片的段落。
因此,这里我们需要对带有图片的笑话进行过滤。
我们可以发现,有图片的段落会有类似下面的代码,而没有图片的段落则不会。 因此,我们的正则表达式的item[3]得到以下内容。 如果没有图片,第[3]项获取的内容为空。
<div class="thumb">
<a href="/article/112061287?list=hot&s=4794990" target="_blank">
<img src="http://pic.qiushibaike.com/system/pictures/11206/112061287/medium/app112061287.jpg" alt="但他们依然乐观">
a>
div>
所以我们只需要判断item[3]是否包含img标签即可。
好吧,我们把上面代码中的for循环改成下面的
for item in items:
haveImg = re.search("img",item[3])
if not haveImg:
print item[0],item[1],item[2],item[4]
现在,整体代码如下
\# -*- coding:utf-8 -*-
import urllib
import urllib2
import re
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)
response = urllib2.urlopen(request)
content = response.read().decode('utf-8')
pattern = re.compile('.*?.*?+
'content">(.*?).*?
运行一下看看效果
好吧,带有图片的笑话已被删除。 这不是很有趣吗?
3、完善交互,设计面向对象模式
好了,现在我们已经完成了核心部分。 剩下的就是修复角落。 我们想要达到的目标是:
按 Enter 阅读笑话,并显示该笑话的发布者、发布日期、内容和点赞数。
另外,我们需要设计面向对象的模型,引入类和方法,并对代码进行优化和封装。 最后我们的代码如下
(来自:我重写了这段代码)
#coding=utf-8
import urllib, urllib2, re
from datetime import datetime
class QSBK:
def __init__(self):
self.enable = False
self.page = 1
self.user_agent = r"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36"
self.headers = {
"User-Agent" : self.user_agent
}
self.catch_url = r'http://www.qiushibaike.com/hot/page/'
self.pattern = re.compile('.*?.*?+
'content">(.*?).*?
好吧,我们来测试一下。 点击回车,会输出一个笑话,包括发帖人、发帖时间、笑话内容和点赞数。 不是很好吗?
我们的第一个实用的爬虫项目就介绍到这里了。 欢迎大家继续关注。 来吧,朋友们!
【转载:精米»爬虫实战实战:爬行糗事百科全书】