爬虫 | 微博热搜采集发送器

本实验将实现一款爬虫工具,微博热搜采集发送器,通过 requests 库加 bs4 库完成对热搜的爬取,之后通过 smtplib 库与 email 库实现邮件信息的传递。最后还为大家介绍了一个爬虫技巧,pandas 一行代码抓取表格数据。

知识点

  • 微博热搜爬取
  • Python 邮件发送
  • pandas 一行代码爬取网页表格

微博热搜爬取

本实验中的目标网站为 微博热搜榜单,即下图中出现的序号,关键词,热度相关信息。

对网站源码进行分析之后,发现数据都存储在下图所示的结构体中,核心以表格标签形式存在:

在编写爬虫的过程中,发现目标网站数据存在一定的问题,例如第一行数据缺少序号与阅读量,第十行数据缺少最右侧的图标。

以上内容在爬虫程序中属于异常数据,在编写代码时需要针对性对其处理,本实验选用之前课程中提及的 requests 库与 bs4 库进行爬取。由于相关知识已经提前学习,直接进入编码环节,具体细节在代码注释中体现。

将如下代码写入 /home/project/wb.py 文件:

下述代码中的 COOKIE ,可通过浏览器访问微博热搜之后,进行获取。

import requests
from bs4 import BeautifulSoup


# 获取网页元素
def get_html():
    # headers 头字典
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
        "Referer": "https://www.baidu.com",
        "cookie": "可先打开浏览器,获取浏览器COOKIE之后,粘贴到该位置"
    }
    # 抓取网页
    res = requests.get("https://s.weibo.com/top/summary", headers=headers)
    # 返回网页内容
    return res.text


def analy_html():

    html = get_html()
    # 通过 lxml 方式解析数据
    soup = BeautifulSoup(html, 'lxml')
    # 查找主 table 标签
    data = soup.find(name="tbody")
    # 发现所有的 tr,即表格中的行
    items = data.find_all(name='tr')

    for item in items:
        # 序号
        order_number = item.find(attrs={"class": "td-01"}).text
        # 容错处理,如果序号为空,设置为 0
        if order_number == "":
            order_number = 0

        # 标题区域所有内容
        title_content = item.find(attrs={"class": "td-02"}).contents
        # 标题
        title = ""
        # 阅读量
        readers = ""
        # 第二个单元格存在多个网页标签,获取第一个与第三个即可
        if len(title_content) > 3:
            print(title_content)
            title = title_content[1].text
            readers = title_content[3].text
        else:
            title = title_content[1].text
            readers = "0"

        # 热度标签
        level = item.find(attrs={"class": "td-03"}).text  # 热度标签

        print(order_number, title, readers, level)


if __name__ == "__main__":
    analy_html()

以上代码可以顺利的输出目标数据:

但是在编写的过程中发现如下问题,这部分内容希望你可以掌握,具体如下。

bs4 库获取所有子标签

在 bs4 库中通过 contents 属性,可以获取某一标签下的所有子标签,返回一个 list,上述代码相关部分如下:

# 标题区域所有内容
title_content = item.find(attrs={"class": "td-02"}).contents

在 bs4 库中与其相似的一些属性如下:

  • children 返回所有的子标签,但是返回的是一个迭代器;
  • descendants 返回所有后代标签,与 contentschildren 最大的区别是,这二者只返回直接子标签;
  • parent 返回某标签的父标签;
  • parents 返回某标签的所有父辈标签;
  • next_siblingprevious_sibling 返回下一兄弟标签和上一兄弟标签;
  • next_siblingsprevious_siblings 返回所有下一兄弟标签和上一兄弟标签。

以上内容在实际的编码中需要结合实际情况进行使用,在使用时如果出现对应的标签无父级标签,无兄弟标签,会直接返回 None

关于父级标签,兄弟标签的相关概念如果你对前端语言不是很熟悉,可以直接在互联网查找一些资料,非常容易理解。

子标签获取到的内容

上文中提及的代码存在一个问题,在使用 contents 属性获取子标签后,得到的 list 包含回车,即 \n 数据。

# 标题
title = ""
# 阅读量
readers = ""
# 第二个单元格存在多个网页标签,获取第一个与第三个即可
if len(title_content) > 3:
    print(title_content)
    title = title_content[1].text
    readers = title_content[3].text

上述代码中输出内容如下,注意到除了基本标签以外,还出现了换行符,此时在获取标题与阅读量的时候,留意索引。

['\n', <a href="/weibo?q=%23%E6%9D%8E%E4%BD%B3%E7%90%A6%E7%BB%99%E9%87%91%E9%9D%96%E8%BF%87%E7%94%9F%E6%97%A5%23&amp;Refer=top" target="_blank">李佳琦给金靖过生日</a>, '\n', <span>227719</span>, '\n']

Python 邮件发送

下面完成本实验第二部分知识,邮件发送,使用 Python3 内置的 smtplib 库即可实现。关于该库的使用教程,属于 Python 基础知识部分内容,本实验中不在对其赘述。

代码编写前需要将对应的邮箱在邮箱后台配置好,当开启邮箱的 SMTP 时,注意是否提供了单独密码,如果提供了要使用 SMTP 密码。

导入对应模块

import smtplib
from email.mime.text import MIMEText   # 定义邮件内容
from email.header import Header  # 定义邮件标题
import time

邮件发送函数如下:

# 邮件发送
def send_email():
    # 发送时间
    rq = time.strftime("%Y-%m-%d")

    # 发送的邮箱
    from_addr = "发送ID@163.com"

    # 发送邮箱SMTP服务器地址
    smtpserver = "smtp.163.com"

    # 密码,填写自己的密码即可,163 邮箱和网页登录的邮箱不同
    password = "邮箱密码"
    # 接收邮箱的账号
    to_addr = "接收ID@qq.com"
    # 多个接收者的时候使用
    # to_addrs = ["接收ID@qq.com", from_addr]

    # 邮件的标题
    subject = "{rq} 微博热搜".format(rq=rq)
    # 邮件为 html 格式,需要把热搜的爬取到的数据进行格式化,analy_html 方法即为获取微博热搜内容
    data = analy_html()
    table = "<table>"
    for item in data:
        table += "<tr><td>{order}:{title}:{readers}:{level}</td></tr>".format(
            order=item[0], title=item[1], readers=item[2], level=item[3])
    table += "</table>"
    content = table
    # 邮件的正文
    msg = MIMEText(content, 'html', 'utf-8')
    # 邮件的标题
    msg['Subject'] = Header(subject, 'utf-8')
    # 邮件发送方
    msg['From'] = from_addr
    # 邮件接收方,发送给一人
    msg['To'] = to_addr
    # 邮件接收方,发送给多人
    # msg['To']=','.join(to_addrs)

    # SSL协议端口号要使用465
    smtp = smtplib.SMTP_SSL(smtpserver, 465)
    # helo 向邮箱标识用户身份
    smtp.helo(smtpserver)
    # 服务器返回结果确认
    smtp.ehlo(smtpserver)
    # 登录邮箱服务器,输入自己的账号和密码
    smtp.login(from_addr, password)
    print("热搜发送中...")
    # 邮件发送多人
    # smtp.sendmail(user,to_addrs,msgroot.as_string())

    # 发送给个人的邮件
    smtp.sendmail(from_addr, to_addr, msg.as_string())
    smtp.quit()
    print("发送完毕")

邮件发送对应的是 HTML 格式数据,记得发送前进行格式的拼接。由于发送邮件的函数中使用了 analy_html 函数,所以调整其的返回值。

def analy_html():
    ...
    items = data.find_all(name='tr')
    # 待发送的内容
    send_msgs = []
    for item in items:
        ...
        # send_msg 列表追加数据
        send_msgs.append ((order_number,title,readers,level))
    return send_msgs

相同部分代码进行了省略。代码对应关键信息修改成自己的信息之后,可以测试邮件发送是否成功,如果完成,你会收到一封如下格式的邮件。

邮件内容如下:

小扩展:微博热搜的采集与发送可以做成定时任务,每日发送一次,这样就能在第一时间收到今日热点信息了。

补充一点:学习 SMTP 可以直接在下述网址学习 菜鸟教程 或者直接百度关键字 Python SMTP

pandas 一行代码爬取网页表格

在爬取微博热搜的过程中,发现目标数据存在与一个表格之中,针对这种类型的数据,有一个小技巧提供给大家,有了它,你可以对网页表格数据实现一行代码抓取。

实现该内容的库就是 pandas ,准确的说该第三方库是一款数据分析库,一般用在数据处理上,但是它提供了一个 read_html 方法,可以实现对网页表格的抓取。

将如下代码写入 /home/project/demo2.py 文件:

import pandas as pd
import requests
from bs4 import BeautifulSoup


# 获取网页元素
def get_html():
    # headers 头字典
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
        "Referer": "https://www.baidu.com",
        "cookie": "可先打开浏览器,获取浏览器COOKIE之后,粘贴到该位置"
    }
    # 抓取网页
    res = requests.get("https://s.weibo.com/top/summary", headers=headers)
    # 返回网页内容
    return res.text

# 读取网页表格
tb = pd.read_html(get_html())
# 获取到的表格数据为 list 类型
print(type(tb))
print(len(tb))
print(tb[0])

实验楼也非常贴心的为咱们预装好了该库,直接测试上述代码即可:

学会了 pandas 的 read_html 方法之后,在碰到网页中数据结构是以表格形式存在的,你解决问题的方法又多了一条

实验总结

从本实验开始,后面的几个内容都是爬虫实际场景应用,我们学习编程的最终目的是将程序应用到工作与生活当中,在学习的过程中,如果你的程序能真正的帮助你解决问题,这样学习效率会变的更高。

爬虫的最佳的场景就是替你完成手动重复的操作,实现自动化处理某些任务,例如本实验中,将爬虫程序与邮件结合,除了采集热搜以外,也可以帮助你监视任意网站,当其出现更新或者变更时,都可以及时的给你发送信息告知于你,希望本爬虫实验可以让你对爬虫的应用场景有所认识。

posted @ 2023-07-30 07:45  张Zong在修行  阅读(165)  评论(0编辑  收藏  举报