爬取糗事百科

# 爬取糗事百科信息。

# 注意:爬取任何一个网站,首先要确定的就是这个网站是静态网站还是动态网站。其次看看这个GET请求是否携带了特殊的参数。最后需要留意请求头中的Cookie信息。

import sqlite3, re
from urllib.request import Request, urlopen
from fake_useragent import UserAgent

class DataTool(object):
    """
    工具类:对提取的元组中的数据,进行整理,删除无效的字符(\n,<br/>)
    """
    # 定义删除\n字符的正则表达式
    pattern_n = re.compile(r'\n', re.S)
    # 定义删除<br/>字符的正则表达式
    pattern_br = re.compile(r'<br/>', re.S)

    def process_tuple_data(self, origin_tuple_data):
        """
        用于对提取的原始元组进行数据处理的函数
        :param origin_tuple_data: 原始数据元组
        :return: 返回整理之后的元组
        """
        # 需要处理的数据:用户昵称、段子内容
        # sub()是正则表达式中的替换数据的方法,需要将\n这个字符替换成空字符
        # 参数:1. 替换规则 2. 替换结果 3. 要匹配的字符串
        nick_name = re.sub(self.pattern_n, '', origin_tuple_data[0])

        # 处理段子内容
        content = re.sub(self.pattern_n, '', origin_tuple_data[2])
        content = re.sub(self.pattern_br, '', content)

        # 将处理后的数据再封装成一个元组,返回
        data = (nick_name, origin_tuple_data[1], content, origin_tuple_data[3], origin_tuple_data[4])
        return data

class DBTool(object):
    """
    将数据保存到数据库中的工具类,主要负责数据库的增删改查操作。
    """
    connect = None
    cursor = None
    # 操作数据库:1.创建数据库的连接对象,创建游标,这两个对象一般连接一次即可;2.数据的增删改查;3.关闭数据库对象、关闭游标对象,一般都是在数据保存完毕之后关闭即可。
    @classmethod
    def create_db_cursor(cls):
        cls.connect = sqlite3.connect('qsbk.db')
        cls.cursor = cls.connect.cursor()

    @classmethod
    def insert_sql(cls, tuple_data):
        """
        执行数据插入sql语句的函数
        :param tuple_data: 使用DataTool工具类整理过后的数据。
        :return:
        """
        sql_str = 'INSERT INTO qs (nick_name, level, content, vote_number, comment_number) VALUES ("%s", "%s", "%s", "%s", "%s")' % (tuple_data[0], tuple_data[1], tuple_data[2], tuple_data[3],tuple_data[4])
        # 开始执行sql语句
        cls.cursor.execute(sql_str)
        cls.connect.commit()

    @classmethod
    def close_db_cursor(cls):
        cls.cursor.close()
        cls.connect.close()

class QSBKSpider(object):
    """
    爬虫类
    """
    def __init__(self):
        # 将各个页面通用的路径,不变的路径声明称为属性,调用方便,直接在这个属性的后面拼接页码。
        self.base_url = 'https://www.qiushibaike.com/hot/page/'
        # 初始化请求头,伪造浏览器请求头中的User-Agent字段值,如果不修改User-Agent字段值,有一个默认的值User-Agent: python-3.7 xxx。
        # self.headers = {
        #     'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.12 Safari/537.36'
        # }
        # 实例化工具类DataTool的对象
        self.tool = DataTool()
        # 实例化ua对象
        self.ua = UserAgent()

    def get_list_html(self, page_num):
        """
        获取每一个列表页的html网页源代码(这个获取的源代码就是 "右键-网页源代码" 中的内容)
        page_num:表示将要请求的页面的页码。
        :return:
        """
        # 构造每一页的url地址
        page_url = self.base_url + str(page_num)
        # 向page_url发送GET请求,开始获取当前页page_num的网页源代码
        # 先构造Request请求对象
        headers = {
            # random属性:从ie、firefox、chrome等浏览器的ua中,随机获取一个ua。
            'User-Agent': self.ua.random
        }
        request = Request(page_url, headers=headers)
        try:
            response = urlopen(request)
        except Exception as e:
            print('请求失败:地址{},原因{}'.format(page_url, e))
            return None
        else:
            # try语句中的请求没有出现异常,就会执行else语句,如果出现异常了就不会执行else语句了。
            # print(response)
            html = response.read().decode()
            return html

    def parse_list_html(self, html):
        """
        解析上一个函数请求的html源代码
        :param html: 请求成功返回列表页的网页源代码,请求失败返回None
        :return:
        """
        if html:
            # 使用正则表达式开始解析网页源代码
            # 写正则注意事项:
            # 1. 尽量找到要匹配的零散数据所在的标签,而且这个标签必须和这些零散的数据一样能够循环。因为findall()函数在循环匹配数据的时候,是按照整个正则表达式规则循环匹配的。
            # 2. 在参考网页中 "审查元素" 来设置正则匹配规则的时候,一定要确认是否和 "网页源代码" 中的标签顺序、属性顺序等保持一致,如果不一致的话,必须参考 "网页源代码" 来设置正则匹配规则。因为 "审查元素" 中的Html代码是经过JS渲染之后的源代码。
            pattern = re.compile(r'<div class="article block.*?>.*?<div class="author clearfix">.*?<h2>(.*?)</h2>.*?<div class="articleGender.*?">(.*?)</div>.*?<div class="content">.*?<span>(.*?)</span>.*?<div class="stats">.*?<i class="number">(.*?)</i>.*?<i class="number">(.*?)</i>', re.S)
            results_list = re.findall(pattern, html)
            for data in results_list:
                new_data = self.tool.process_tuple_data(data)
                DBTool.insert_sql(new_data)
        else:
            print('html源代码为None')


if __name__ == '__main__':
    # 创建数据库对象、游标对象
    DBTool.create_db_cursor()

    obj = QSBKSpider()

    # 循环爬取多页数据。
    for x in range(1, 10):
        # range()取1到10之间的整数,能取到1,无法取到10
        html = obj.get_list_html(x)
        obj.parse_list_html(html)

    # 关闭数据库、游标对象
    DBTool.close_db_cursor()

# fake_user_agent:pip install fake-useragent 这个第三方库,它维护了各种主流浏览器的UA标识,并且会定期的更新这个库,淘汰一些过期的UA。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355

推荐阅读更多精彩内容