python爬虫之糗事百科

历经1个星期的实践,终于把python爬虫的第一个实践项目完成了,此时此刻,心里有的只能用兴奋来形容,后续将继续加工,把这个做成一个小文件,发给同学,能够在cmd中运行的文件。简化版程序,即单单爬取页面数据如下

#目标爬取糗事百科热门段子,实现每次回按一次就显示一个段子的发布时间,发布人,段子内容,点赞数
#过滤带有图片的段子
# -*- coding:utf-8 -*-
import urllib
import urllib2
import chardet
import re

#page代表的是页面
page =3
#url代表的是页面地址
url='http://www.qiushibaike.com/hot/page/'+str(page)
#headers验证
user_agent='Mozilla/4.0(compatible;MSIE 5.5; Windows NT)'
#设置headers headers={}是头域的内容  User-Agent表示的是浏览器的地址,user_agent就是上面的伪装浏览器的地址
headers ={ 'User-Agent': user_agent}
try:
    #词条语句是request构造
    #1.向服务器发送请求
    request = urllib2.Request(url,headers=headers)
    #2.服务器响应请求
    response=urllib2.urlopen(request).read()
    #3.读取响应   response是响应的意思
    print ("该网页使用的编码是:%s" %(chardet.detect(response)))    
    response=response.decode('utf-8')
    
    pattern=re.compile('<div class="author clearfix">.*?<h2>(.*?)</h2>.*?<div class="content">.*?<span>(.*?)</span>.*?</div>(.*?)<div class="stats">.*?<i class="number">(.*?)</i>.*?</span>',re.S)
    items=re.findall(pattern,response)
    for item in items:
        haveImg=re.search("img",item[2])
        if not haveImg:
            print item[0],item[1],item[3]
    
    
    
#错误显示提示
except urllib2.URLError, e:
    if hasattr(e,"code"):
        print e.code
    if hasattr(e,"reason"):
        print e.reason

加强版添加了交互信息的如下

# coding=utf-8
import urllib
import urllib2
import re
import thread
import time

class QSBK:

    def __init__(self):
        self.pageIndex = 1
        self.user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
        self.headers = {'User-Agent' :self.user_agent}
        self.stories = []
        self.enable = False

    def getPage(self,pageIndex):
        try:
            url = 'http://www.qiushibaike.com/hot/page/' + str(pageIndex)
            request = urllib2.Request(url,headers=self.headers)
            response = urllib2.urlopen(request)
            pageCode = response.read().decode('utf-8')
            return pageCode
        except urllib2.URLError,e:
            if hasattr(e,"reason"):
                print "error",e.reason
                return None

    def getPageItems(self,pageIndex):
        pageCode = self.getPage(pageIndex)
        if not pageCode:
            print "page load error"
            return None
        pattern = re.compile('<div class="author clearfix">.*?<h2>(.*?)</h2>.*?<div class="content">.*?<span>(.*?)</span>.*?</div>(.*?)<div class="stats">.*?<i class="number">(.*?)</i>.*?</span>',re.S)
        items = re.findall(pattern,pageCode)
        pageStories = []
        for item in items:
            pageStories.append([item[0].strip(),item[1].strip(),item[2].strip(),item[3].strip()])
        return pageStories

    def loadPage(self):
        if self.enable==True:
            if len(self.stories)<2:
                pageStories = self.getPageItems(self.pageIndex)
                if pageStories:
                    self.stories.append(pageStories)
                    self.pageIndex +=1

    def getOneStory(self,pageStories,page):
        for story in pageStories:
            input = raw_input()
            self.loadPage()
            if input == "Q":
                self.enable = False
                return
            print u"第%d页\t发布人:%s\t 赞:%s\n%s" %(page,story[0],story[3],story[1])

    def start(self):
        print u'正在读取,回车查看,Q退出'
        self.enable = True
        self.loadPage()
        nowPage = 0
        while self.enable:
            if len(self.stories)>0:
                pageStories = self.stories[0]
                nowPage +=1
                del self.stories[0]
                self.getOneStory(pageStories,nowPage)

spider = QSBK()
spider.start()

以上代码由于当时使用静觅大神的交互代码,无法运行出应有的效果,且尝试修改了许多遍还是无法得出,所以参考了菜虫的代码,修改了正则表达式,可用,但没有去除含有图片的数据

静觅大神源网址http://cuiqingcai.com/990.html     菜虫源网址https://github.com/hhzzer/python/blob/master/qiubai1.0.py

修改后的正则表达式

'<div class="author clearfix">.*?<h2>(.*?)</h2>.*?<div class="content">.*?<span>(.*?)</span>.*?</div>(.*?)<div class="stats">.*?<i class="number">(.*?)</i>.*?</span>'

我参考进行修改后的程序,交互界面排除了含有图片的数据,代码如下

# -*- coding:utf-8 -*-
import urllib
import urllib2
import chardet
import thread
import re


#爬取糗事百科爬虫
class QSBK:
    
    #初始化方法,定义一些变量
    def __init__(self):
        #代表页面是1pageindex代表页索引
        self.pageIndex=1
        #存放段子的变量,每一个元素是每一页的段子stories
        self.stories=[]
        #存放程序是否继续运行的变量
        self.enable=False
        #headers验证
        self.user_agent='Mozilla/4.0(compatible;MSIE 5.5; Windows NT)'
        #设置headers headers={}是头域的内容  User-Agent表示的是浏览器的地址,user_agent就是上面的伪装浏览器的地址
        self.headers ={ 'User-Agent': self.user_agent}
    #传入某一页的索引获得页面代码
    def getPage(self,pageIndex):        
        try:
            #url代表的是页面地址
            url='http://www.qiushibaike.com/hot/page/'+str(pageIndex)            
            #词条语句是request构造
            #1.向服务器发送请求
            request = urllib2.Request(url,headers=self.headers)
            #2.服务器响应请求
            response=urllib2.urlopen(request).read()
       print ("该网页使用的编码是:%s" %(chardet.detect(response)))
#3.读取响应 response是响应的意思 pageCode=response.decode('utf-8') return pageCode except urllib2.URLError,e: if hasattr(e,"reason"): print "error",e.reason return None #传入某一页代码,返回本页不带图片的段子子列表 def getPageItems(self,pageIndex): pageCode=self.getPage(pageIndex) if not pageCode: print "page load error" return None #使用正则表达式的compile语句规范抓取的信息 pattern=re.compile('<div class="author clearfix">.*?<h2>(.*?)</h2>.*?<div class="content">.*?<span>(.*?)</span>.*?</div>(.*?)<div class="stats">.*?<i class="number">(.*?)</i>.*?</span>',re.S) #使用正则表达式的findall语句从response中寻找规范信息的内容 items=re.findall(pattern,pageCode) pageStories=[] #for循环在抓取的items信息内容中 for item in items: #在item【2】是否存在img字符,img字符存在即表示有图片,是否含有图片 haveImg=re.search("img",item[2]) #如果没有haveImg,即没有图片就输出 if not haveImg: replaceBR=re.compile('<br/>') text=re.sub(replaceBR,"\n",item[1]) #item[0]是段子的发布者,item[1]是内容,item[3]是获赞数 pageStories.append([item[0].strip(),text.strip(),item[2].strip(),item[3].strip()]) return pageStories #加载并提取页面内容,加入到列表中 def loadPage(self): #如果当前为看的页面少于2页,则加载新一页 if self.enable == True: if len(self.stories)<2: #获取新一页 pageStories=self.getPageItems(self.pageIndex) #将该页的段子存放在list中 if pageStories: self.stories.append(pageStories) #获取完之后页码索引加一,表示下次读取下一页 self.pageIndex +=1 #调用该方法,每次敲回车打印输出一个段子 def getOneStory(self,pageStories,page): #遍历一页段子 for story in pageStories: #等待用户输入 input =raw_input() #每当输入回车一次,判断一下要加载新页面 self.loadPage() #如果输入q则程序结束 if input =="Q": self.enable=False return print u"第%d页\t发布人:%s\t赞:%s\n%s"%(page,story[0],story[3],story[1]) #开始方法 def start(self): s='正在读取糗事百科,按回车看新段子,按q退出' print s.decode('utf-8') #使变量为ture,程序可以正常运行 self.enable=True #先加载一页内容 self.loadPage() #局部变量,控制当前读到了第几页 nowPage=0 while self.enable: if len(self.stories)>0: #从全局list中获取一页的段子 pageStories=self.stories[0] #当前读到的页数+1 nowPage +=1 #将全局list中第一个元素删除,因为已经取出 del self.stories[0] #输出该页的段子 self.getOneStory(pageStories,nowPage) spider=QSBK() spider.start() #目标爬取糗事百科热门段子,实现每次回按一次就显示一个段子的发布人,段子内容,点赞数 #过滤带有图片的段子 _author_='lxf'

效果如图



遇到了很多问题,下面一一提出我所解决的办法
1.attributeError:QSBKinstance has no attribute ‘start’实例没有属性的开始
如何解决的:将工程的所有def对其,包含start的格式对其问题,python对空格和table看的很严重
2.在交互界面中,即界面中,coding:utf-8必须在第一排,且前面没有任何汉字
不然出现类似错误UnicodeEncodeError: 'gbk' codec can't encode character u'\xaf' in position 1: illegal multibyte sequence
3.程序长期运行不出来结果且不报错,原因可能1.正则表达式错误2.可能pageStories书写错误
4.indexError:list index out of range原因pageStories.append与要输出的print  u"第%d页\t发布人:%s\t赞:%s\n%s"%(page,story[0],story[3],story[1])不同,超出范围,目前的猜测,得进一步验证。
验证完毕
如图所示


5.出现类型错误!类型字节或bytearray的预期对象得到!type‘instance,
6.关于编码问题出现输出加u'
print (u"该网页使用的编码是:%s" %(chardet.detect(response)))解决中文乱码璇ョ綉椤典娇鐢ㄧ殑缂栫爜鏄細
还有更多细节,但没有养成及时记录的习惯导致现在无法记得,涨教训了,觉得收获很大,但是现在记起来的却很少。
实际上现在版本的糗事百科不知道什么原因就算不处理采集回来的信息也不会带有图片,只要在getonestory那里修改输出信息不加入图片的那个就行了
区别只在于判断了是否带图片它输出的仅仅是几条不带图片的糗事,而没判断的加了图片不加图片都显示文字出来,而且判断了的运行时间比不判断要长很多时间




 

posted @ 2017-07-13 17:11  子不语怪力乱神  阅读(717)  评论(0编辑  收藏  举报