Python3 学习札记(五)

参考‘逆風的薔薇’的教程,《Python3爬虫》-单线程爬取我的CSDN全部博文

代码


import urllib.request, re, time, random, gzip

# 定义保存文件函数
def saveFile(data, i):
    # path = r'E:\Python\VSCode_Python\CSDN\project\05_papers\papers_"+str(i+1)+".txt'
    path = "E:\\Python\\VSCode_Python\\CSDN\\project\\05_papers\\paper_"+str(i+1)+".txt"
    file = open(path, 'wb')
    page = '当前页:'+str(i+1)+'\n'
    # 换行符采用\n,则生成的txt文件用Windows自带的记事本打开后没有换行,需要用其他文本编辑器,如果换行符采用\r\n即回车换行,则自带记事本也可以
    file.write(page.encode('gbk'))
    # 将博文信息写入文件(以utf-8保存的文件声明为gbk)
    for d in data:
        d =  str(d)+'\n'
        file.write(d.encode('gbk'))
    file.close()

# 解压缩数据
def ungzip(data):
    try:
        data = gzip.decompress(data)
    except:
        print('未经压缩,无需解压...')
    return data

# CSDN爬虫类
class CSDNSpider:

    def __init__(self, pageIdx = 1, url = 'http://blog.csdn.net/fly_yr/article/list/1'):
        self.pageIdx = pageIdx
        self.url = url[0:url.rfind('/') + 1] + str(pageIdx) # rfind() 返回字符串最后一次出现的位置(从右向左查询),如果没有匹配项则返回-1
        self.headers = {
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
            'Accept-Encoding': 'gzip, deflate',
            'Accept-Language': 'zh-CN,zh;q=0.8',
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3141.7 Safari/537.36',
            # 'Referer': 'http://blog.csdn.net/fly_yr/article/details/72187057',
            'Upgrade-Insecure-Requests': '1',
            'Host': 'blog.csdn.net',
            'Proxy-Connection': 'keep-alive'
        }

    def getPages(self):
        req = urllib.request.Request(url=self.url, headers=self.headers)
        res = urllib.request.urlopen(req)
        # 解压缩
        data = res.read()
        data = ungzip(data)
        data = data.decode('utf-8')

        pages = r'<div.*?pagelist">.*?<span>.*?共(.*?)页</span>'
        # 计算博文总页数
        pattern = re.compile(pages, re.DOTALL)
        pagesNum = re.findall(pattern, data)[0]
        return pagesNum

    # 设置要抓取的博文页面
    def setPage(self, idx):
        self.url = self.url[0:self.url.rfind('/')+1] + str(idx)

    # 读取博文信息
    def readData(self):
        ret = []
        # chrome浏览器 开发者模式查看源代码,从而确定正则表达式
        str = r'<span class="link_title"><a href="(.*?)">\s*(.*?)\s*</a>.*?<span class="link_postdate">(.*?)</span>.*?'+\
              r'<span class="link_view" title="阅读次数">.*?阅读</a>\((.*?)\)</span>.*?'+\
              r'<span class="link_comments" title="评论次数">.*?评论</a>\((.*?)\)</span>'
        req = urllib.request.Request(url=self.url, headers=self.headers)
        res = urllib.request.urlopen(req)

        # 内容解压缩
        data = res.read()
        data = ungzip(data)
        data = data.decode('utf-8')
        pattern = re.compile(str, re.DOTALL)    # (DOTALL模式下,.也能匹配换行符)
        items = re.findall(pattern, data)
        for item in items:
            # ret.append(item[0]+'年'+item[1]+'月'+item[2]+'日'+'\t'+item[3]+'\n标题'+item[5]
            # +'\n连接:http://blog.csdn.net'+item[4]
            # +'\n'+'阅读:'+item[6]+'\t评论:'+item[7]+'\n')
            ret.append('时间:'+item[2]+'\n'+'标题:'+item[1]
            +'\n'+'链接:http://blog.csdn.net'+item[0]
            +'\n'+'阅读:'+item[3]+'\t'+'评论:'+item[4]+'\n')
        return ret

cs = CSDNSpider()   # 实例化一个类时,只执行__init__
pagesNum = int(cs.getPages())
print('博文总页数:', pagesNum)

for idx in range(pagesNum):
    cs.setPage(idx)
    print('当前页:', idx+1)
    papers = cs.readData()
    saveFile(papers, idx)

运行结果

生成文件列表,共有22页博文,生成22个txt文件:
这里写图片描述
每个txt文件表示每一页博文所包含的所有文章,paper_1.txt如下:
这里写图片描述

笔记

  • 对于要匹配的正则表达式,一定要根据网页源码来实现,具体正则表达式的语法比较复杂,可以简单参考此链接作以简单了解Python正则表达式指南
  • 关于换行符,\n,or,\r\n, or,\r,区别参考
  • rfind,返回字符串最后一次出现的位置(从右向左查询),如果没有匹配项则返回-1
  • -
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值