Python爬虫实践笔记(一)

无登录爬取糗事百科段子

第一步:获取页面源码

(1)先确定我们要爬取的页面的url,然后通过页面的开发者工具查看需要发送的headers信息。这里,糗事百科需要我们添加User-Agent这个头文件信息,不然建立连接会失败的。
(2)通过urllib2的Request(url, data, headers)函数生成一个请求包。data和headers都是可选的。这里不需要传递data但是要传递headers,必须在传递实参时写明headers = XXX,不然编译器不知道你传的是哪个数据的实参。
(3)通过urllib2的urlopen(req)函数来发送请求包并建立连接,函数返回一个响应。需要注意的是,可能会出现连接失败的情况,所以可以使用异常处理机制try-except来捕获异常,输出异常信息,比在编译时出现一大串信息要好。
(4)使用返回的响应对象的read()方法读取页面信息,通过decode(‘utf-8’)函数使页面信息解码成utf-8的数据,方便之后的处理。

重点:
①请求的data和headers
②异常处理
③信息读取和解码

第二步:提取所需信息

(1)由于上一步获取的页面的源代码,我们需要通过正则表达式来提取我们需要的信息,如发布人,被赞数以及段子文本。这里,我们必须仔细查看页面的源代码,看看我们的信息在哪里,然后使用正则表达式来匹配。使用re模块的compile函数生产字符模式pattern。这个pattern在所有的re模块函数中都会用到。
(2)将pattern作为实参传递给findall函数,找到符合要求的字符串。在这里就是要匹配到所有段子所在的部分,以列表的形式作为findall的返回值返回,列表的元素为一个匹配成功的字符串。
(3)使用循环逐个处理每一个成功匹配的字符串。
(4)根据应用把所需的信息存储起来。

重点:
①查看源代码的布局。
②最常用的正则表达式部分是 .? ,这是非贪婪模式的最长匹配,也就是说一旦匹配到 ? 后面的字符就立刻停止匹配。加上括号(.?)分组后可以让我们在之后使用分组内的信息,所以对于要提取的信息必须用 (.?) 匹配。
③提取了信息后,可以根据应用需要进行字符串上的修改。因为提取的信息可能还包含诸如 <br/> <script type="math/tex" id="MathJax-Element-945">
</script>等html符号,还有空格,空行,所以要获取干净的文本必须进行处理。

第三步:构建程序逻辑

(1)这一步比较工程化,只需要把上述步骤封装好,确定好程序的逻辑,就可以自顶向下地编写代码了。可以用面向对象的方法来构建一个爬虫类,提高代码的重用性。

重点:
①要注意python面向对象的特点,例如类方法中的参数第一个都是指向实例的参数,不能漏。
②类的成员,不管是数据成员还是成员函数,都需要通过self.XXX的方式调用,而且不要跟自己声明的局部变量混淆了。
③如果在输入input函数中显示中文要是用一下方式unicode(‘XXX’, ‘utf-8’).encode(‘gbk’)。

程序部分:自己实现的程序

下面是我实现的根据页数爬取糗事百科中的段子,并显示出来的程序。

__author__ = 'HJX'
# _*_ coding: utf-8 _*_
import re
import urllib
import urllib2
import thread
import time

class QSBK2:
    '糗事百科爬虫2'
    def __init__(self):
        self.pageIndex = 1;
        self.url = 'https://www.qiushibaike.com/hot/page/'+str(self.pageIndex);
        self.user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36'
        self.headers = {'User-Agent' : self.user_agent}
        self.stories = []

    def getPageCode(self):
        try:
            req = urllib2.Request(self.url, headers = self.headers)
            res = urllib2.urlopen(req)
            pageCode = res.read().decode('utf-8')
            return pageCode
        except urllib2.URLError, e:
            if hasattr(e, 'reason'):
                print u'获取源码失败,原因是:', e.reason
                return None

    def getStories(self):
        stories = []
        pageCode = self.getPageCode()
        if not pageCode:
            print u'获取当前页面段子失败!'
            return None
        pattern = re.compile('<div.*?author clearfix">.*?<h2>(.*?)</h2>.*?content">.*?span>(.*?)</span>.*?number">(.*?)</i>', re.S)
        items = re.findall(pattern, pageCode)
        for item in items:
            publisher = item[0].strip()
            br = re.compile('<br/>')
            text = re.sub(br, '\n', item[1])
            vote = item[2].strip()
            stories.append([publisher, text, vote])
        return stories

    def showStories(self):
        if len(self.stories) == 0:
            print u'当前页数没有段子!'
        else:
            for story in self.stories:
                publisher = story[0]
                text = story[1]
                vote = story[2]
                print u'发布人:%s\t\t被赞数:%s\n%s\n' % (publisher, vote, text)

    def start(self):
        print u'-----糗事百科爬虫阅读器,根据页数看段子-----'
        while 1:
            self.pageIndex = input(unicode('请输入您要看的页数,输入0退出程序:', 'utf-8').encode('gbk'));
            if self.pageIndex == 0:
                print u'程序已退出!'
                break
            self.stories = self.getStories()
            self.showStories();

spider = QSBK2()
spider.start()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值