Python爬虫实践笔记(一)

xiaoxiao2021-02-27  250

无登录爬取糗事百科段子

第一步:获取页面源码

(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()
转载请注明原文地址: https://www.6miu.com/read-8564.html

最新回复(0)