Python爬虫教程——实用爬虫百科全书

2024-05-07 -

大家好,前面已经讲了这么多基础知识了。 现在我们来做几个实际的项目来挑战一下。 那么这次我就给大家带来一个《尴尬事百科》中爬行小笑话的例子。

首先,大家都听说过《尴尬故事百科全书》吧? 尴尬的朋友发布了很多有趣的笑话。 这次我们尝试使用爬虫来捕获它们。

温馨的提示

前段时间尴尬事百科进行了修改,导致之前的代码变得无法使用,导致无法输出,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">(.*?).*?
(.*?)
(.*?)',re.S) items = re.findall(pattern,content) for item in items: haveImg = re.search("img",item[3]) if not haveImg: print item[0],item[1],item[2],item[4] except urllib2.URLError, e: if hasattr(e,"code"): print e.code if hasattr(e,"reason"): print e.reason

运行一下看看效果

好吧,带有图片的笑话已被删除。 这不是很有趣吗?

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">(.*?).*?
(.*?)
(.*?).*?' + 'class="number">(.*?).*?
',re.S) def get_content_with_page(self, page): try: request = urllib2.Request(self.catch_url+str(page), headers=self.headers) response = urllib2.urlopen(request) return response.read() except urllib2.URLError, e: if hasattr(e, "code"): print(e.code) if hasattr(e, "reason"): print(e.reason) return "" def get_stories_from_content(self, content): return re.findall(self.pattern, content) def start(self): self.enable = True while self.enable: content = self.get_content_with_page(self.page) stories = self.get_stories_from_content(content) if len(stories) > 0: for item in stories: hasPicture = re.search('img', item[3]) if not hasPicture: print 'author:' + item[0].strip() print 'content:' + item[1].strip() print 'time:' + str(datetime.fromtimestamp(float(item[2])) ) print 'praise:' + item[4] print 'comment:' +item[5] print('按Enter继续...') input = raw_input() self.page += 1 spider = QSBK() spider.start()

好吧,我们来测试一下。 点击回车,会输出一个笑话,包括发帖人、发帖时间、笑话内容和点赞数。 不是很好吗?

我们的第一个实用的爬虫项目就介绍到这里了。 欢迎大家继续关注。 来吧,朋友们!

【转载:精米»爬虫实战实战:爬行糗事百科全书】

版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权本站发表,未经许可,不得转载。

扫一扫在手机阅读、分享本文

推荐阅读