Crawler battle (3): анализ пользовательской информации Weibo

задняя часть база данных Python GitHub рептилия анализ данных визуализация данных

Предисловие

Серия статей:

Crawler battle (1): сканирование пользовательской информации Weibo

Боевой краулер (2): Selenium имитирует вход в систему и сканирует информацию

Crawler battle (3): анализ пользовательской информации Weibo

Что описывает эта серия статей?

1. Поисковый анализ и методы обработки

2. Метод работы с базой данных в Python

3. Автоматизация браузера Selenium и использование безголового браузера

4. Метод анализа облака слов на данных

5. Способы визуализации данных

6.LDAНеявное распределение ДирихлеКак моделировать и использовать модель

предисловие

Переднийэта статьяВ этом документе представлен процесс сканирования информации и динамики пользователей Weibo и сохранения данных в базе данных. Давайте поговорим о процессе данных базы данных и анализа.

Анализ базы данных

Во-первых, давайте рассмотрим поля базы данных, рассмотренные в предыдущей статье. На картинке нижеweiboТри таблицы в базе:

oXauR.png

Значение каждого поля см.исходный код.

Давайте посмотрим на содержимое каждой таблицы в базе данных, прежде всего на содержимое таблицы пользовательских данных:

oXLLy.png

Вы можете видеть, что это соответствует информации на странице профиля Weibo.

Давайте посмотрим на таблицу динамических данных пользователя:

oXEGi.png

Он содержит пользовательский динамический контент и динамическое время выпуска, поэтому сначала мы подумали, что сможем обрабатывать динамический контент Weibo.

Визуальный анализ

Поняв структуру базы данных, мы можем визуализировать динамику микроблогов и динамическое время публикации.Здесь автор проводит следующий анализ:

  • Динамическая обработка времени публикации в Weibo: нарисуйте статистический график времени публикации в Weibo.
  • Простая визуализация динамики Weibo: облако слов
  • Динамическая обработка частоты слов Weibo: статистика частоты слов и генерация карты частоты слов

Вышеупомянутые три процедуры анализа расположены вData_analysis.py, код его основной функции выглядит следующим образом:

#可以指定需要分析的用户的uid(必须先存在conf.yaml里面,并且运行了一次爬虫程序)
def main(uid):
    time_lists,str=get_time_str(uid)#将数据库中的微博动态转化为字符串
    plot_create_time(time_lists)#画出微博发布时间统计图
    with open('data/stop_words.txt') as f:
        stop_words = f.read().split('\n')
    str=format_content(str)#去掉表情和一些不必要的符号
    word_list=word_segmentation(str,stop_words)#分词并去除停用词
    create_wordcloud(word_list) #画出词云
    counter = word_frequency(word_list, 10)# 返回前 top_N 个值,如果不指定则返回所有值
    print(counter)
    plot_chart(counter)#会生成词频图保存在weibo_wordfrq.html中

Итак, как реализовать эти три вида анализа?Далее автор объяснит их один за другим.

Статистика времени выпуска Weibo

Для визуального анализа динамического контента Weibo первым шагом является интеграция динамического контента Weibo.Следующий код объединяет всю динамику в Weibo пользователя, которая является первой строкой в ​​основной функции.Функция, вызываемая кодом .

# time_lists,str=get_time_str(uid)# main 函数第一行代码
# 将数据库中的微博动态转化为字符串
def get_time_str(uid):
    _, engine = Connect('../conf.yaml')  # 连接数据库
    conn = engine.connect()
    metadata = MetaData(engine)
    wb_data = Table('wb_data',metadata, autoload=True)
    s = select([wb_data]).where(wb_data.c.uid == uid) #从wb_data表中选择uid对应的数据
    res = conn.execute(s)
    conn.close()
    str = ''
    time_lists = []
    for row in res:
        str += row[2] + '\n'#拼接动态字段
        time_lists.append(row[3]) #将时间转化为列表对象,方便后续处理
    return time_lists, str

вернутьtime_listsДля динамического списка времени выпуска,strОкончательная строка, которая динамически склеена вместе.Здесь, поскольку время подсчитывается, нам нужно только обратить внимание наtime_listsЭтот список. Давайте посмотрим на конкретный контент, хранящийся в этом списке:

[....,'02月02日 29', '01月21日 30', '01月20日 31', '01月10日 32', '01月02日 33', '01月01日 34', '2017-11-30', '2017-11-29', '2017-11-04', '2017-10-29', '2017-10-27',...]

Этот раздел я взял сознательно, и бывает, что время в обоих форматах включено. Время, содержащееся в этом списке, начинается с самого последнего месяца и даты до исходной даты года-месяца.'2017-11-30'Предыдущий формат датыХХ месяц ХХ день ХХ,а также'01月01日 34'Последний такой же20XX-XX-XX, отсортированные от ближнего к дальнему. Здесь я рассматриваю возможность анализа тенденции количества и времени микроблогов, размещаемых каждый день, и распределяю время так, чтобы чем дальше от настоящего, тем ближе к происхождению.

Итак, есть следующий код:

# plot_create_time(time_lists)# main 函数第二行代码
#画出微博发布时间的统计图
def plot_create_time(time_lists):
    recent_time = re.compile(r'\d{2}月\d{2}日',re.S)
    long_time = re.compile(r'(\d{4}-\d{2}-\d{2})',re.S)
    tmp_lists = []#保存**月**日格式的数据
    tmp_nums = []#统计**月**日发帖数量
    long_lists = []#保存20**-**-**格式的数据
    long_nums = []#统计20**-**-**发帖数量
    for t in time_lists:
        res = re.findall(recent_time, t)
        if(res):#res[0]为**月**日格式的数据
            if(not tmp_lists or res[0]!= tmp_lists[-1]):#列表为空或者不与前一个日期重复
                tmp_lists.append(res[0])
                tmp_nums.append(1)
            else:#与前一个日期重复,计数加一
                tmp_nums[-1]+=1
        else:#res[0]20**-**-**格式的数据
            res = re.findall(long_time,t)

            if(not long_lists or res[0]!=long_lists[-1]):
                long_lists.append(res[0])
                long_nums.append(1)
            else:
                long_nums[-1]+=1
    #将时间按照从远到进的顺序排列
    tmp_lists.reverse()
    tmp_nums.reverse()
    long_lists.reverse()
    long_nums.reverse()
    time_list = long_lists + tmp_lists
    time_nums = long_nums + tmp_nums
    
    #调用 pyecharts 包渲染出统计图
    chart = Bar('用户微博动态发布时间')
    chart.add('动态数', time_list, time_nums, is_more_utils=True,datazoom_range=[10,40],is_datazoom_show=True)
    chart.render("weibo_dynamic.html")

Таким образом, рисуется график статистики времени выпуска Weibo, который является динамическим графиком, и эффект выглядит следующим образом:

weibo_dynamic.gif

анализ облака слов

Для анализа динамического содержания мы должны сначала выполнить сегментацию слов, а мы знаем, что в общеупотребительных словах много модальных частиц, что повлияет на вес ключевых слов, поэтому перед анализом эти слова нужно удалить.Такие слова называются в поиск информации.стоп-слова. Кроме того, необходимо удалить ненужные символы, такие как разрывы строк и HTML-коды, содержащиеся в динамике.

Таким образом, основная функция имеет следующие четыре строки кода, прежде чем получить облако слов:

with open('data/stop_words.txt') as f:#从保存有停用词的文件中读取停用词
        stop_words = f.read().split('\n')
str=format_content(str)# 去掉表情和一些不必要的符号
word_list=word_segmentation(str,stop_words)#分词并去除停用词

который вызываетword_segmentationфункция, содержание функции следующее:

# 分词并去除停用词
def word_segmentation(content, stop_words):
    # 使用 jieba 分词对文本进行分词处理
    jieba.enable_parallel()
    seg_list = jieba.cut(content)
    seg_list = list(seg_list)

    # 去除停用词
    user_dict = [' ', '哒']
    filter_space = lambda w: w not in stop_words and w not in user_dict
    word_list = list(filter(filter_space, seg_list))

    return word_list

Здесь я используюjiebaВыполните сегментацию слов, отфильтруйте результаты сегментации слов, удалите стоп-слова и верните список результатов сегментации слов. затем используйтеword_listДанные для рисования облака слов, конкретный код выглядит следующим образом:

#create_wordcloud(word_list) # main 函数第7行代码
#画出词云
def create_wordcloud(content,image='weibo.jpg',max_words=5000,max_font_size=50):

    cut_text = " ".join(content)
    cloud = WordCloud(
        # 设置字体,不指定就会出现乱码
        font_path="HYQiHei-25J.ttf",
        # 允许最大词汇
        max_words=max_words,
        # 设置背景色
        # background_color='white',
        # 最大号字体
        max_font_size=max_font_size
    )
    word_cloud = cloud.generate(cut_text)
    word_cloud.to_file(image)

В итоге получаем результат weibo.jpg , открываем и смотрим:

weibo.jpg

Это результат анализа облака слов. Читатели могут добавлять стоп-слова для фильтрации в соответствии со своими потребностями.

обработка частоты слов

Статистическая обработка частоты слов в динамике Weibo требует сначала списка слов, потому что ванализ облака словУ нас есть список слов с отфильтрованными стоп-словами.word_list, поэтому его можно использовать прямо здесь:

#counter = word_frequency(word_list, 10)# main 函数倒数第三行代码
# 词频统计
# 返回前 top_N 个值,如果不指定则返回所有值
# from collections import Counter
def word_frequency(word_list, *top_N):
    if top_N:
        counter = Counter(word_list).most_common(top_N[0])
    else:
        counter = Counter(word_list).most_common()

    return counter

принадлежитcounterСодержимое представляет собой список слов и их вхождений, например:

[('感觉', 11), ('代码', 10), ('说', 9),('晚上', 9), ('终于', 7), ('麻蛋', 6), ('写', 6), ('数据', 5), ('学校', 5), ('朋友', 4)]

Затем нарисуйте и визуализируйте на основе полученной частоты слов:

# plot_chart(counter)# main 函数最后一行,会生成词频图保存在weibo_wordfrq.html中
#画出词频图,默认为柱状图
def plot_chart(counter, chart_type='Bar'):
    items = [item[0] for item in counter]
    values = [item[1] for item in counter]

    if chart_type == 'Bar':
        chart = Bar('微博动态词频统计')
        chart.add('词频', items, values, is_more_utils=True)
    else:
        chart = Pie('微博动态词频统计')
        chart.add('词频', items, values, is_label_show=True, is_more_utils=True)

    chart.render('weibo_wordfrq.html')

Наконец, получите диаграмму статистики частотности 10 слов:

weibowordfrq.gif

LDA-анализ

Мы были заняты в течение длительного времени и проводили различные анализы пользовательской динамики, но у нас до сих пор нет четкого представления о предпочтениях и личных ощущениях пользователя.В настоящее время нам нужно использовать метод для извлечения ключевых частей из массива информацию, желательно такую, которая может извлечь тему, предметэтот предыдущий документВдохновленный [1], автор узнал, что LDA — хороший метод анализа, который может удовлетворять вышеуказанным условиям.

Неявное распределение Дирихле(английский язык: скрытое распределение Дирихле, сокращенно LDA) — это тематическая модель, которая дает тему каждого документа в наборе документов в виде распределения вероятностей. В то же время это неконтролируемый алгоритм обучения, который не требует ручной маркировки обучающей выборки во время обучения, только набор документов и количество заданных тем k. Кроме того, еще одним преимуществом LDA является то, что для каждой темы можно найти несколько слов для ее описания.

Приведенное выше описание взято из Википедии.

Эта статья ориентирована на практику, поэтому она только знакомит с методом использования LDA для анализа в python и не объясняет принцип работы LDA. Более того, на академических лекциях по информатике и науке о данных, когда докладчики представляют LDA, они часто сразу пропускают основную часть.

Эта часть кода находится вLDA_Analysis.py, вы можете сначала посмотреть на содержимое функции main:

def main(uid):
    wordlists, uid = getwords(uid)#获取分词列表
    lda, tf, tf_feature_names, tf_vectorizer = word2vec(wordlists)#将单词转化为向量
    Save_Topic_Words(lda, tf_feature_names, uid)#保存主题到数据库
    pyLDAvisUI(lda, tf, tf_vectorizer)#根据主题结果进行渲染

Первый шаг — разметить и отфильтровать стоп-слова, как и раньше, вызвавgetwordsфункция, код выглядит следующим образом:

#获取微博动态数据
def getwords(uid):
    _,str = get_time_str(uid)  # 将数据库中的微博动态转化为字符串,可以指定uid(conf.yaml里面的)
    with open('data/stop_words.txt') as f:
        stop_words = f.read().split('\n')
    str = format_content(str)
    word_list = word_segmentation(str, stop_words)  # 分词并去除停用词
    return word_list,uid

Содержимое этой функции такое же, как и эффект в Data_analysis.py, введенный ранее, поэтому здесь он не повторяется.

Затем используйте метод обработки LDA, который поставляется с пакетом машинного обучения sklearn, Код выглядит следующим образом:

#lda, tf, tf_feature_names, tf_vectorizer = word2vec(wordlists)# main 函数第二行代码
#使用LDA进行微博动态主题建模与分析
def word2vec(word_list,n_features=1000,topics = 5):
    tf_vectorizer = CountVectorizer(strip_accents='unicode',
                                    max_features=n_features,
                                    #stop_words='english',已经进行过停用词处理故不用重复处理
                                    max_df=0.5,
                                    min_df=10)
    tf = tf_vectorizer.fit_transform(word_list)

    lda = LatentDirichletAllocation(n_components=topics,#主题数
                                    learning_method='batch',
                                   #样本量不大只是用来学习的话用"batch"比较好,这样可以少很多参数要调
                                    )
    #用变分贝叶斯方法训练模型
    lda.fit(tf)

    #依次输出每个主题的关键词表
    tf_feature_names = tf_vectorizer.get_feature_names()

    return lda,tf,tf_feature_names,tf_vectorizer #返回模型以及主题的关键词表

Наконец, мы представляем тему в виде визуального результата:

#pyLDAvisUI(lda, tf, tf_vectorizer) # main 函数中最后一行
#将主题以可视化结果展现出来
def pyLDAvisUI(lda,tf,tf_vectorizer):

    page = pyLDAvis.sklearn.prepare(lda, tf, tf_vectorizer)
    pyLDAvis.save_html(page, 'lda.html')        #将主题可视化数据保存为html文件

Получите lda.html , который является результатом после рендеринга:

topic.gif

На этом внедрение анализа пользовательской информации завершено.

Адрес источника:GitHub.com/звездопад/S…

Ссылка: [1] Лу Фей, Анализ социальных сетей и майнинг для социальной инженерии [D], Шанхай: Шанхайский университет Цзяотун, 2013.