• Python2爬取内涵段子


    代码git地址:https://github.com/DemonYan/spider_study
    后续爬虫相关代码都会在git上进行更新,请持续关注

    本文分享自己学爬虫的一个代码。该代码实现的是使用urllib2爬取http://www.neihanpa.com/article/网站的段子。
    小编也正处于学习python的阶段,如有什么错误,欢迎留言指出。

    一、实现环境

    mac 10.13.2

    python 2.7

    使用模块:urllib2

    二、实现源码

    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    #author: Demon
    
    import urllib2
    import random
    import re
    import os
    
    # 定义多个User-Agent
    header_list = [
            "Mozilla/5.0(Macintosh;U;IntelMacOSX10_6_8;en-us)AppleWebKit/534.50(KHTML,likeGecko)Version/5.1Safari/534.50"
            "Mozilla/5.0(Macintosh;IntelMacOSX10.6;rv:2.0.1)Gecko/20100101Firefox/4.0.1"
            "Opera/9.80(Macintosh;IntelMacOSX10.6.8;U;en)Presto/2.8.131Version/11.11"
            "Mozilla/5.0(Macintosh;IntelMacOSX10_7_0)AppleWebKit/535.11(KHTML,likeGecko)Chrome/17.0.963.56Safari/535.11"
            "Mozilla/4.0(compatible;MSIE7.0;WindowsNT5.1;Trident/4.0;SE2.XMetaSr1.0;SE2.XMetaSr1.0;.NETCLR2.0.50727;SE2.XMetaSr1.0)"
    ]
    
    
    def getRandomUserAgent():
        """
            随机得到一个User-Agent
        """
        return random.choice(header_list)
    
    class Neihanpa:
        def __init__(self):
            # 网站的基础url
            self.baseUrl = "http://www.neihanpa.com/article"
            # 起始页码
            self.page = 1
    
            # 匹配每条段子的正则表达式
            # 默认.在单行中进行匹配(.不匹配换行符)
            # re.S 表示进行全文匹配,开启DOTALL模式,即使得. 也可以匹配换行符
            # .* : 尽可能多匹配(贪婪模式)
            # .*? : 尽可能少匹配
            self.pattern_page_div = re.compile(r'<div class="text-column-item box box-790">(.*?)</div>', re.S)
    
            # 由于由网站的列表页爬出来的段子是不完整的,需要根据里面的url点进去,才能看到完整的数据
            # 匹配出每个段子中的请求链接,用于获取完整的段子
            self.pattern_div_href = re.compile(r'/d+.html', re.S)
    
            # 匹配完整的段子
            # 由于根据列表页的url再次访问得到的页面,肯定只有一个段子,而且段子的每句话是由<p></p>标签分隔的
            # 所以,这里不需要加re.S,就能拿到每个句子组成的一个list
            self.pattern_p = re.compile(r'<p>(.*)</p>')
    
            # 对最终的格式进行处理
            # &(.*?) 匹配HTML里的一些实体字符,比如 
            # s 匹配空白字符和换行符
            # ' '是一个全角空格,s不能匹配到
            self.pattern_content = re.compile(r"&(.*?);|s| ")
    
            # 定义存储所有段子的文件名
            self.saved_filename = "duanzi.txt"
    
        def dealPage(self, html):
            """
                处理从网站列表页中获取到的每个段子
                从而获取能得到完整段子的url列表
            """
            div_list = self.pattern_page_div.findall(html)
            url_list = []
            for div_content in div_list:
                href_list = self.pattern_div_href.findall(div_content)
                for href in href_list:
                    url_list.append(href)
            return url_list
    
    
        def loadPage(self, url):
            """
                根据url爬取页面
                如果爬取发生错误,直接过滤
            """
            try:
                request = urllib2.Request(url)
                request.add_header("User-Agent", getRandomUserAgent())
                response = urllib2.urlopen(request)
                return response.read()
            except urllib2.HTTPError, e:
                return ""
    
    
        def writePage(self, content_list):
            """
                将获取到的段子写入文件
            """
            with open(self.saved_filename, "a") as f:
                for content in content_list:
                    deal_content = self.pattern_content.sub("", content)
                    f.write(deal_content)
                    f.write("
    ")
                f.write("
    
    ")
    
    
        def spider(self):
            """
                处理页码信息并调用相关方法
            """
            if self.page == 1:
                url = self.baseUrl + "/index.html"
                # 当爬取第一页时,判断文件是否存在
                if os.path.exists(self.saved_filename):
                    # print "removed" # 调试
                    os.remove(self.saved_filename)
            else:
                url = self.baseUrl + "/index_%s.html" % (self.page)
            self.page+=1
            html = self.loadPage(url)
            if html == "":
                return
            duanziUrl_list = self.dealPage(html)
            for duanziUrl in duanziUrl_list:
                print "段子%s爬取成功!" % (duanziUrl)
                duanziHtml = self.loadPage(self.baseUrl + duanziUrl)
                duanzi_list = self.pattern_p.findall(duanziHtml)
                self.writePage(duanzi_list)
    
    def main():
        neihanpa = Neihanpa()
        while True:
                operation = raw_input("输入Q退出,输入回车继续:")
                if operation.lower() == 'q':
                        break
    
                neihanpa.spider()
    
    if __name__ == "__main__":
        main()
    

    三、代码解释

    首先,刚开始接触Python爬虫,所以使用的是urlib2+正则表达式的方式来对爬取的数据进行的处理。当然有更好更方便的方式,后续会对这个代码进行持续的更新。比如改用request模块等

    其次,这个网站,在显示段子列表页里,只显示了段子的一部分内容,所以在代码里爬取列表页获取到部分段子,通过对获取到的部分段子进行处理,拿到能得到完整段子的url,再进行进一步的爬取


    最近刚配置了一下vim编辑器,使它可以显示行号,代码能自动提示,同时能显示文档结构。然后更改了主题(程序员对这种暗黑色的代码主题都情有独钟啊)。配置过程遇到很多问题,有时间会再总结下相关操作。
    我的配置效果如下图所示:
    图片描述

  • 相关阅读:
    codevs1430 素数判定
    codevs1212 最大公约数
    codevs1012 最大公约数和最小公倍数问题
    codevs1160 蛇形矩阵
    Debate CodeForces
    Divide Candies CodeForces
    Login Verification CodeForces
    Colorful Bricks CodeForces
    ExaWizards 2019 English D
    Cards and Joy CodeForces
  • 原文地址:https://www.cnblogs.com/yrrAwx/p/8407967.html
Copyright © 2020-2023  润新知