Python爬虫(八)-项目完结

Python爬虫入门目录

爬虫数据的获取到这里完结了,之后还有一个利用flask搭建展示页面的项目。

源码

蓝奏云下载:https://mwhls.lanzous.com/iUI5ifzchod,记得将后缀改为.py

# coding=utf-8

from bs4 import BeautifulSoup
import re
import urllib.request
import urllib.error
import xlwt
import sqlite3


def main():
    baseUrl = "http://mwhls.top/page/"                  # 基础网址,观察首页网址得知每页只有最后一个数字不同
    # 爬取网页
    dataList = getData(baseUrl)                         # 获得爬虫数据
    # 保存数据
    savePath = ".\\"                                    # 存储文件夹
    saveDataXls(dataList, savePath)                     # 存储为XLS表格
    saveDataDB(dataList, savePath)                      # 存储为数据库


# 正则表达式匹配规则
findLink = re.compile(r'<a href="(.*)">')               # 匹配文章链接
findTitle = re.compile(r'rel="bookmark">(.*)</a>')      # 匹配文章标题
findExcerpt = re.compile(r'<div class="entry excerpt">.*<p>(.*)</p>', re.S)     # 匹配概述,re.S表示匹配时跳过换行符
findImage = re.compile(r'src="(.*)" srcset')            # 匹配图像链接
findPostView = re.compile(r'count">(\d*)</span>')       # 匹配阅读数


# 爬取网页
def getData(baseUrl):
    dataList = []
    page = 0
    while(page>=0):                                     # 搜索循环
        page += 1
        url = baseUrl + str(page)                       # 页面地址更新
        html = askUrl(url)                              # 获取页面html文本

        if html == "":                                  # 404时,html为空,即已获取玩全部页面,结束循环
            break

        soup = BeautifulSoup(html, "html.parser")       # 使用html解析来处理html变量(变量名)
        for item in soup.find_all("article"):           # 匹配article标签
            data = []
            item = str(item)                            # 转换为字符串格式

            title = re.findall(findTitle, item)         # 标题获取
            data.append(title[0])
            link = re.findall(findLink, item)           # 链接获取
            data.append(link[0])
            excerpt = re.findall(findExcerpt, item)     # 概述获取
            excerpt = excerpt[0].replace('<br/>', ' ')  # 去除概述中换行符
            data.append(excerpt)
            getPostData(data, link[0])                  # 阅读数量获取
            image = re.findall(findImage, item)         # 图片地址获取
            data.append(image[0])

            dataList.append(data)                       # 将所有截取的数据添加进数据存储列表

    # for data in dataList:                             # 打印列表,查看是否正确
    #     for item in data:
    #         print(item)
    #     print()
    return dataList


def getPostData(dataList, url):                         # 获取文章内数据
    html = askUrl(url)
    soup = BeautifulSoup(html, "html.parser")
    item = soup.find_all(class_="post-views-count")     # 找到span标签,且class为post-views-count。
    item = str(item)
    postView = re.findall(findPostView, item)           # 获取阅读数量
    dataList.append(postView[0])
    return dataList


def askUrl(baseUrl):
    html = ""
    head = {                                            # 模拟头部信息,发送信息
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36"
        }
    request = urllib.request.Request(baseUrl, headers=head) # 封装请求
    try:
        response = urllib.request.urlopen(request)      # 发送请求
        html = response.read().decode("utf-8")          # 用utf8编码响应
    except urllib.error.URLError as e:                  # 错误代码显示,这里一定会显示一次404 Not Found,因为查询功能会以404页面作为终止
        if hasattr(e, "code"):
            print(e.code)
        if hasattr(e, "reason"):
            print(e.reason)
    return html


# 保存数据
def saveDataXls(dataList, savePath):
    xlsPath = savePath + "mwhls.top.xls"                # 存储位置初始化
    book = xlwt.Workbook(encoding="utf-8")              # 使用utf8编码
    sheet = book.add_sheet("mwhls.top", cell_overwrite_ok=True)
    dataName = ('文章名',
                '文章链接',
                '文章概述',
                '阅读数',
                '封面链接')
    for i in range(0, 5):                               # 写入列名
        sheet.write(0, i, dataName[i])
    for row in range(len(dataList)):                    # 写入数据
        data = dataList[row]
        for col in range(0, 5):
            sheet.write(row+1, col, data[col])
    book.save(xlsPath)                                  # 保存为xls文件


def initDB(dbPath):
    createSql = """
        create table mwhls
        (
        id integer primary key autoincrement,
        title varchar,
        link text,
        information text,
        view numeric,
        image text
        )
    """                                         # 数据库创建语句
    connect = sqlite3.connect(dbPath)           # 数据库连接
    cursor = connect.cursor()                   # 游标获取
    cursor.execute(createSql)                   # 语句执行
    connect.commit()                            # 提交执行操作
    connect.close()                             # 关闭数据库连接


def saveDataDB(dataList, savePath):
    dbPath = savePath + "mwhls.top.db"          # 初始化数据库路径
    initDB(dbPath)                              # 初始化数据库
    connect = sqlite3.connect(dbPath)           # 连接数据库
    cursor = connect.cursor()                   # 游标获取
    for data in dataList:                       # 对每篇文章数据进行数据库插入
        for index in range(len(data)):          # 将非整形数据添加"",防止执行出错
            if index != 3:                      # 第4个位置,即列表中序号3的地方,存放的是阅读量,是整形,因此不能添加""
                data[index] = '"' + data[index] + '"'
        insertSql = '''
            insert into mwhls(
            title, link, information, view, image) 
            values(%s)
        ''' % (",".join(data))                  # 插入语句,%后的是插入的值,即将列表用,分割,然后拼成字符串,因此使用join
        cursor.execute(insertSql)               # 语句执行
        connect.commit()                        # 语句提交
    connect.close()                             # 数据库连接关闭


if __name__ == "__main__":
    main()

结语

项目正常运行会出现一次404 Not Found,这个提示是在getData中使用askUrl调用最后一页的下一页时出现的,用来判断是否读取完所有页面。

如果还有其他问题请留言。

You may also like...

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注