鱼C论坛

 找回密码
 立即注册
查看: 1596|回复: 0

[作品展示] selenium微博_登录_抓取疫情评论_存储数据库

[复制链接]
发表于 2020-9-22 16:57:27 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
# -*- coding: utf-8 -*-
"""
Created on Wed Jul 22 16:40:18 2020

@author: HCF
"""
import urllib.parse
from selenium.webdriver import Chrome, ChromeOptions
import time
import requests
import chaojiying
import urllib
import random
import traceback
import re
import datetime
from lxml import etree
import pymysql
import json


def get_conn():
    """
    :return: 连接,游标l
    """
    # 创建连接
    conn = pymysql.connect(host="localhost",
                           user="root",
                           password="123456789",
                           db="cov",
                           charset='utf8mb4')
    # 创建游标
    cursor = conn.cursor()  # 执行完毕返回的结果集默认以元组显示
    return conn, cursor


def close_conn(conn, cursor):
    if cursor:
        cursor.close()
    if conn:
        conn.close()


def query(sql, *args):
    """
    封装通用查询
    :param sql:
    :param args:
    :return: 返回查询到的结果,((),(),)的形式
    """
    conn, cursor = get_conn()
    cursor.execute(sql, args)
    res = cursor.fetchall()
    close_conn(conn, cursor)
    uids, dts = [], []
    for r in res:
        uids.append(r[0])
        dts.append(r[1])
    return uids, dts

#转换时间
def check_time(date):
    if '今天' in date:
        a, b = date.split()
        t = time.strftime("%Y-%m-%d") + ' ' + b + ':' + '00'
    elif '分钟前' in date:
        a, b = date.split('分钟前')  # 利用时间撮计算
        timestemp = int(time.time()) - int(a) * 60
        ltime = time.localtime(timestemp)
        t = time.strftime("%Y-%m-%d %H:%M:%S", ltime)
    elif '秒前' in date:
        a, b = date.split('秒前')
        timestemp = int(time.time()) - int(a)
        ltime = time.localtime(timestemp)
        t = time.strftime("%Y-%m-%d %H:%M:%S", ltime)
    else:
        li = re.findall("\d+", date)
        t = datetime.date(2020, int(li[0]), int(li[1])).strftime('%Y-%m-%d') + ' ' + li[2] + ':' + li[3] + ':' + '00'
    return t

#模拟下拉
def drop_down():
    for x in range(1, 11, 2):
        time.sleep(1)
        j = x / 10  # 下拉几次
        js = 'document.documentElement.scrollTop = document.documentElement.scrollHeight * %f' % j
        driver.execute_script(js)

#获取评论
def outputtext(html):
    global a
    html = etree.HTML(html)
    commentlist = html.xpath('//div[@class="list_ul"]/div[@class="list_li S_line1 clearfix"]')
    content = []
    id = []
    tt = []
    conn, cursor = get_conn()
    sql = "insert into comments_p(user_id,content,dt,nichen,jianjie,gender,address) values(%s,%s,%s,%s,%s,%s,%s)"
    try:
        for div in commentlist:
            text = div.xpath('.//div[@class="list_con"]/div[@class="WB_text"]/text()')
            g1 = ''
            for c in text:
                if c.strip() == '':
                    pass
                else:
                    g1 += c.strip()
            content.append(g1)  # 评论内容
            g1 = g1[1:]
            g2 = div.xpath('.//div[@class="list_con"]/div[@class="WB_text"]/a/@usercard')
            id.append(g2[0])  # 评论idd
            g2 = g2[0][3:]#评论者id
            g3 = div.xpath(
                './/div[@class="list_con"]/div[@class="WB_func clearfix"]/div[@class="WB_from S_txt2"]/text()')
            g3 = check_time(g3[0])
            tt.append(g3)  # 评论时间
            if len(g1):
                try:
                    ############################person###############
                    nichen,jianjie,gender,address = get_address(g2)
                except json.decoder.JSONDecodeError as e:
                    print(e)
                    time.sleep(random.choice([180,190,200]))
                    continue
                try:
                    cursor.execute(sql, (g2, g1, g3,nichen,jianjie,gender,address))  # 插入数据
                except UnicodeEncodeError as e:
                    print(g2, ':', e)
                    nichen = '---含表情---'
                    jianjie = '---含表情---'
                    cursor.execute(sql, (g2, g1, g3,nichen,jianjie,gender,address))  # 插入数据
                a += 1
        conn.commit()  # 提交事务保存数据
    except:
        traceback.print_exc()
    finally:
        close_conn(conn, cursor)
    print(content, '\n', id, '\n', tt, '\n')


def login():
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Safari/537.36'
    }
    # driver.maximize_window()  # 最大化浏览器
    time.sleep(8)
    driver.find_element_by_xpath('//*[@id="loginname"]').send_keys(num1)  # 输入搜索框
    driver.find_element_by_xpath('//*[@id="pl_login_form"]/div/div[3]/div[2]/div/input').send_keys(
        num2)  # 输入搜索框
    driver.find_element_by_xpath('//*[@id="pl_login_form"]/div/div[3]/div[6]/a').click()  # 模拟点击
    time.sleep(3)
    try:
        img_url = driver.find_element_by_xpath('//a[@class="code W_fl"]/img').get_attribute('src')
        response = requests.get(img_url, headers=headers)
        with open('yzm.jpg', 'wb') as f:
            f.write(response.content)
        code = chaojiying.run('yzm.jpg')
        # code = input('请输入验证码:')
        driver.find_element_by_xpath('//*[@id="pl_login_form"]/div/div[3]/div[3]/div/input').send_keys(code)  # 输入搜索框
        driver.find_element_by_xpath('//*[@id="pl_login_form"]/div/div[3]/div[6]/a').click()  # 模拟点击
    except Exception as e:
        print(e)
    driver.refresh()
    cookies = driver.get_cookies()
    # print(cookies)
    return cookies


def comment_id():
    title = ['新冠肺炎', '新冠疫情', '肺炎疫情', '抗击疫情', '抗击肺炎']
    # title = ['新冠疫情']
    # t1 = int(time.time()*1000)#时间戳
    mids = []
    urls = []
    for ti in title:
        key = urllib.parse.quote(ti)
        url = 'https://s.weibo.com/weibo?q={}&wvr=6&b=1&Refer=SWeibo_box'.format(key)
        driver.get(url)
        drop_down()
        time.sleep(1)
        # url1 = 'https://m.weibo.cn/detail/4529896124847833'
        divs = driver.find_elements_by_xpath('//div[@class="card-wrap"]')
        url_divs = driver.find_elements_by_xpath('//p[@class="from"]/a')
        for div in divs:
            mid = div.find_element_by_xpath('.').get_attribute('mid')
            if mid:
                mids.append(mid)
        for url_div in url_divs:
            mid = url_div.find_element_by_xpath('.').get_attribute('href')
            if len(mid) > 60 and mid[:17] == 'https://weibo.com':
                urls.append(mid)
        print(len(mids), len(urls))
    conn, cursor = get_conn()
    sql = "insert into artical_id(mid,url) values(%s,%s)"
    try:
        for i in range(len(mids)):
            cursor.execute(sql, (mids[i], urls[i]))
        conn.commit()  # 提交事务保存数据
    except:
        traceback.print_exc()
    finally:
        close_conn(conn, cursor)
    return mids, urls


def comments(mids):
    for mid in mids:
        time.sleep(0.5)
        data = {
            'ajwvr': 6,
            'id': mid,
            'root_comment_max_id': None,
            'root_comment_max_id_type': 0,
            'root_comment_ext_param': '',
            'page': 1,
            'filter': 'hot',
            'filter_tips_before': 0,
            'from': 'singleWeiBo',
            '__rnd': int(time.time() * 1000)
        }
        base_url = 'https://weibo.com/aj/v6/comment/big?{}'
        url = base_url.format(urllib.parse.urlencode(data))

        # url='https://weibo.com/aj/v6/comment/big?ajwvr=6&id=4464915978680109&root_comment_max_id=4465043019735365&root_comment_max_id_type=1&root_comment_ext_param=&page=28&filter=hot&sum_comment_number=589&filter_tips_before=1&from=singleWeiBo&__rnd=158745889554'
        while True:
            time.sleep(0.5)
            print(url)
            driver.get(url)
            # time.sleep(0.3)
            html = driver.page_source
            html = html.encode('utf-8').decode('unicode_escape')
            html = html.replace('&', '&')
            a = html.find('&root_comment_max_id=')
            max_id = html[a + 21:a + 22]
            print('忽略', max_id)
            key = html[a - 19:a + 170]
            b = key.find('"')
            url1 = key[:b]
            url = 'https://weibo.com/aj/v6/comment/big?ajwvr=6&{}&from=singleWeiBo&__rnd={}'.format(url1, int(
                time.time() * 1000))
            # print(url)
            a1 = html.find('pre-wrap;">') + 11
            b1 = html.find('</pre>', a1)
            html = html[a1:b1]  # 字典
            a2 = html.find('"html":"') + 8
            b2 = html.find(',"count"') - 1
            c = html[a2:b2]  # 内置html
            d = c.replace('&lt;', '<')
            e = d.replace('&gt;', '>')
            f = e.replace('\/', '/')

            outputtext(f)
            if a == -1:
                break


def get_address(uid):
    url = f'https://m.weibo.cn/api/container/getIndex?containerid=230283{uid}_-_INFO&title=%E5%9F%BA%E6%9C%AC%E8%B5%84%E6%96%99&luicode=10000011&lfid=230283{uid}'
    driver.get(url)
    html = driver.page_source
    html = html.encode('utf-8').decode('unicode_escape')
    html = html.replace('&amp;', '&')
    html = html.replace('\/', '/')
    a1 = html.find('pre-wrap;">') + 11
    b1 = html.find('</pre>', a1)
    html = html[a1:b1]  # 字典
    html = json.loads(html)
    try:
        nichen = html['data']['cards'][0]['card_group'][1]['item_content']
    except IndexError as e:
        print(uid, ':', e)
        nichen = '---无名氏---'
    try:
        jianjie = html['data']['cards'][0]['card_group'][2]['item_content']
    except:
        jianjie = None
    try:
        gender = html['data']['cards'][1]['card_group'][1]['item_content']
    except IndexError as e:
        print(uid, ':', e)
        gender = random.choice(['男', '女'])
    try:
        address = html['data']['cards'][1]['card_group'][3]['item_content']
        if html['data']['cards'][1]['card_group'][3]['item_name'] != '所在地':
            address = html['data']['cards'][1]['card_group'][4]['item_content']
    except:
        try:
            address = html['data']['cards'][1]['card_group'][2]['item_content']
        except:
            address = gender
            # gender = None
            gender = random.choice(['男', '女'])
    return nichen,jianjie,gender,address



def chroms():
    option = ChromeOptions()  # 创建谷歌浏览器实例
    option.add_argument('window-size=1920x3000')
    option.add_argument("--headless")  # 隐藏浏览器
    option.add_argument('--disable-gpu')
    option.add_argument('--hide-scrollbars')
    driver = Chrome(options=option)
    return driver


if __name__ == "__main__":
    num1 = #账号
    num2 = #密码
    while True:
        a = 1
        driver = chroms()
        driver.get('https://weibo.com/')
        cookies = login()
        print('\n', f"{time.asctime()}开始更新评论数据", '\n')
        mids, urls = comment_id()  # 文章id
        # mids=['4463193382931883']
        comments(mids)
        driver.quit()
        print('\n', f"{time.asctime()}评论数据更新结束", '\n')
        time.sleep(3600)






想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-18 15:56

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表