我的爬虫学习之旅 (七) 爬虫实战之微博评论爬取

前言:

由于在学习python的过程中对数据库的相关内容没有接触,所以本次结合爬虫与数据库来做这一方面的补充学习。

对于python数据库的学习使用PyMySql,PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb。


一、pymysql快速入门:

 

  • 创建数据库链接对象
  • 使用数据库连接对象创建游标对象
  • 使用游标对象执行sql语句
  • sql执行的结果通过游标对象的方法可获取
  • 关闭数据库链接

首先,需保证创建了数据库TESTDB。

import pymysql

# 数据库链接
db = pymysql.connect("localhost","root","123456","TESTDB" )

# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()
# sql用字符串保存
sql = "SELECT VERSION()"
# 使用 execute()  方法执行 SQL 查询
cursor.execute(sql)

# 使用 fetchone() 方法获取单条数据.
data = cursor.fetchone()

print("%s" % data)

# 关闭数据库连接
db.close()

8.0.12 # 数据库版本

 创建数据库表:

import pymysql

db = pymysql.connect('localhost', 'root', '123456', 'testdb')

cursor = db.cursor()

cursor.execute("drop table if exists EMPLOYEE")

sql = """create table employee(
first_name VARCHAR(20) not null,
last_name VARCHAR(20),
age INT,
sex VARCHAR(10),
income FLOAT )
"""
cursor.execute(sql)

db.close()

更新数据表中数据:

对数据表进行更新操作改变了表中的数据,所以需要向数据库提交操作db.commit(),以及操作出错时的回滚db.rollback()

sql = """INSERT INTO employee VALUES (
"Ralph","Lauren",30,"男",50000
)
"""

try:
    cursor.execute(sql)
    # 执行后需要向数据库提交操作
    db.commit()
except:
    # 发生错误时回滚
    db.rollback()

db.close()

查询操作:

查询Mysql使用 fetchone() 方法获取单条数据, 使用fetchall() 方法获取多条数据,fetchmant(m)方法获取m条数据。

sql = """
SELECT * FROM employee WHERE income > 10000
"""

try:
    cursor.execute(sql)
    results = cursor.fetchall()
    for items in results:
        f_name = items[0]
        l_name = items[1]
        age = items[2]
        sex = items[3]
        income = items[4]

        print("name: %s-%s age: %d sex: %s income: %f" %(f_name, l_name, age, sex, income))
except:
    print("Error: Unable to fetch data")

db.close()

注意:这里对数据库的查询操作不涉及对数据库内容的更改,所以不需要向数据库提交操作以及出错时的回滚操作。


二、实战之爬取微博评论:

现在用目前所掌握的知识技能来对新浪微博的评论进行爬取。

网上有很多关于微博爬取的教程,在这里我选择最简单的方式,对微博移动端的页面进行爬取,并将数据存储在数据库中。

众所周知,微博的站点有三种形式:

  • 微博网页(PC)端:http://weibo.com
  • 微博手机端:http://m.weibo.cn
  • 微博移动端:http://weibo.cn

对于爬取难度来讲,PC端的网页构成是最复杂的,接下来是手机端,然后是移动端;依次打开这三个界面可以发现规律:最丑的界面便是最好爬的微博端!!!于是这次争对移动端的微博评论进行爬取。

首先打开移动端界面,进入需要爬取的微博评论页面,这次选取当日评论数较多的一条微博,发现这条关于何炅的生日动态评论拥有34万条!没错就决定是你了。

我的爬虫学习之旅 (七) 爬虫实战之微博评论爬取_第1张图片

之后F12打开浏览器的开发者模式,依次翻页查看URL找出规律

 https://weibo.cn/comment/HrCZzvR6L?uid=1195230310&rl=0&page=1

https://weibo.cn/comment/HrCZzvR6L?uid=1195230310&rl=0&page=2

https://weibo.cn/comment/HrCZzvR6L?uid=1195230310&rl=0&page=3

 发现URL中的page记录着评论的页数,uid选项则针对着不同的微博用户!

找到这个规律后,再对页面的详细元素进行分析:

可以通过Elements列表观察网页的标签构成,发现用户的评论与信息都在一个

标签中,用id来区分不同的用户。

用户名在该

标签下的第一个标签中,而评论内容在的标签中。

我的爬虫学习之旅 (七) 爬虫实战之微博评论爬取_第2张图片

接下来通过发现的规律来获取用户名与用户的评论,并保存在mysql中。

在这里由于用户的评论所在标签 中还含有类似于表情符号等无用标签信息,所以需要想办法过滤掉它们。

结合前面的知识,分别用正则,BS,XPATH等三种解析库分别对评论内容进行爬取:

 

import requests
from requests.exceptions import RequestException
import pymysql
import time
from bs4 import BeautifulSoup
from lxml import etree
import re

def get_one_page(url):
    try:
        headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36',
            'cookie': 'ALF=1557996154; SCF=Ag_QL3A8f6F5i0Hd0c2LnQoxcaSTbUvwE_n4EGM3PgrqUhBE2_VcWk7GhTgbaopWxlEquyh6B7BNOS4yMpwKjbE.; SUB=_2A25xseUqDeRhGedG7VUW9ynOyj2IHXVTXYtirDV6PUNbktAKLRXxkW1NUQ0tFmomqDUJHrjsyVrNrYf9v3LIE5sj; SUBP=0033WrSXqPxfM725Ws9jqgMF55529P9D9WhAFufpxC4WlO-qNqYU32UW5JpX5KMhUgL.Fo2RSoMNS0MEeK22dJLoI7fKqg4oIsLoIs8_Ms8k; SUHB=05iLV2kTQ86woM; MLOGIN=1; _T_WM=86917107804',
            'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
            'accept-encoding': 'gzip, deflate, br',
            'accept-language': 'zh-CN,zh;q=0.9',
            'dnt': '1'
        }
        response = requests.get(url, headers = headers)
        if response.status_code == 200:
            print("页面获取成功!")
            return response.text
        else:
            print("页面获取失败,状态码:%d" %response.status_code)
            return None
    except RequestException:
        print("页面请求失败")
        return None

def write_to_db(user, comment):
    db = pymysql.connect('localhost', 'root', '123456', 'weibo_testdb')
    cursor = db.cursor()
    #
    sql = """INSERT INTO weibo_comments (user, comment)VALUES("%s", "%s")""" % (
    user, comment)

    try:
        cursor.execute(sql)
        db.commit()
    except:
        db.rollback()

    db.close()


def BSparse_one_page(content):
    soup = BeautifulSoup(content, 'lxml')
    comments_list = soup.find_all('div', class_='c', id=re.compile(r'C_.+'))    # find_all括号中多个内容表示并列关系
    for item in comments_list:
        #print(item.select('.ctt')[0].text) # select后存储在列表里且只有一个元素,用下标[0]将其取出再获得标签文字属性
        user = item.a.text
        comment = re.sub('<.*?>|回复<.*?>:', '', str(item.select('.ctt')[0])).strip()
        if len(comment) == 0:   # 去除空白评论的转发
            continue
        write_to_db(user, comment)

def REparse_one_page(content):
    my_pattern = re.compile('
(.*?)',item) comment = re.sub('<.*?>|回复<.*?>|@.*?<.*?>:','', comment_res.group(1)).strip() # 去除@以及回复等无用文本 if len(comment) == 0: # 去除空白评论的转发 continue write_to_db(user.group(1), comment) def XPparse_one_page(content): # 因为不支持编码声明的Unicode字符串,所以这里要做一次二进制数据转换,若content是response.content的返回就不会报错 content = bytes(bytearray(content, encoding='utf-8')) html = etree.HTML(content) info_list = html.xpath('//div[contains(@id,"C_")]') for item in info_list: user = item.xpath('.//a/text()')[0] comment_res = item.xpath('.//span[@class = "ctt"]/text()') comment = re.sub('回复|:|//.*?', '', ''.join(comment_res)).strip() if len(comment) == 0: # 去除空白评论的转发 continue write_to_db(user, comment) def main(): for page in range(10): print("正在爬取第%d页的评论" %(page+1)) url = 'https://weibo.cn/comment/HrCZzvR6L?uid=1195230310&page=' + str(page+1) content = get_one_page(url) # BSparse_one_page(content) # REparse_one_page(content) # XPparse_one_page(content) time.sleep(2) # 休息一下,玄学防止封ip if __name__ == '__main__': main()

最终在数据库中查看爬取结果:

我的爬虫学习之旅 (七) 爬虫实战之微博评论爬取_第3张图片


 

你可能感兴趣的:(Python爬虫学习之旅)