Python автоматически сканирует и анализирует объем чтения статей — Nuggets Column Edition

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

Практический анализ данных, доступный каждому. Содержание охватывает: поисковый робот, анализ данных, визуализацию данных, сохранение данных в файлы csv и excel, а также передачу параметров командной строки. Небольшой, но полный.

1. Подготовка

1.1 Используемая технология

  • python3
  • запросы: HTTP-сканирование данных json
  • панды: анализировать, сохранять данные
  • matplotlib: анализ визуализации данных

1.2 Установка

Если он уже установлен, пропустите.

pip install requests
pip install pandas
pip install matplotlib

1.3 Импорт

import requests
import pandas as pd
import matplotlib.pyplot as plt
# %matplotlib inline

2. Анализ URL

2.1 Скопируйте URL-адрес запроса интерфейса json

Войдите на личную домашнюю страницу Nuggets, откройте инструменты разработчика, перейдите на вкладку «Столбцы» и скопируйте URL-адрес в инструменты разработчика «Сеть-> XHR-> Имя-> get_entry_by_self-> Заголовки-> URL-адрес запроса».

Например, мой: 'timeline-merger-immediately.Nuggets.IM/V1/Individual_Um внезапно…'

Если вам не терпится увидеть эффект, вы можете сразу перейти к разделу 6 этой статьи после копирования этого URL-адреса.

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

2.2 Анализ URL-адресов

Назначьте URL, скопированный выше, коду нижеjuejin_zhuanlan_api_full_urlПеременная.

juejin_zhuanlan_api_full_url = 'https://timeline-merger-ms.juejin.im/v1/get_entry_by_self?src=web&uid=5bd2b8b25188252a784d19d7&device_id=1567748420039&token=eyJhY2Nlc3NfdG9rZW4iOiJTTcVRGQ1BseWdTZHF4IiwicmVmcmVzaF90b2tlbiI6ImJHZkJDVDlWQkZiQUNMdTYiLCJ0b2tlbl90eXBlIjoibWFjIiwiZXhwaXJlX2luIjoyNTkyMDAwfQ%3D%3D&targetUid=5bd2b8b25188252a784d19d7&type=post&limit=20&order=createdAt'

def decode_url(url):
    adr, query = url.split("?")
    params = { kv.split("=")[0]:kv.split("=")[1] for kv in query.split("&")}
    return adr, params

decode_url(juejin_zhuanlan_api_full_url)

вывод:

('https://timeline-merger-ms.juejin.im/v1/get_entry_by_self',
 {'src': 'web',
  'uid': '5bd2b8b25188252a784d19d7',
  'device_id': '156774842039',
  'token': 'eyJhY2Nlc3NfdG9rZW4iOiJTTHVPcVRGeWdTZHF4IiwicmVmcmVzaF90b2tlbiI6ImJHZkJDVDlWQkZiQUNMdTYiLCJ0b2tlbl90eXBlIjoibWFjIiwiZXhwaXJlX2luIjoyNTkyMDAwfQ%3D%3D',
  'targetUid': '5bd2b8b25188252a784d19d7',
  'type': 'post',
  'limit': '20',
  'order': 'createdAt'})

3. Захват данных

Вспомогательная функция:

def encode_url(url, params):
    query = "&".join(["{}={}".format(k, v) for k, v in params.items()])
    return "{}?{}".format(url, query)

def get_juejin_url(uid, device_id, token):
    url = "https://timeline-merger-ms.juejin.im/v1/get_entry_by_self"
    params = {'src': 'web',
              'uid': uid,
              'device_id': device_id,
              'token': token,
              'targetUid': uid,
              'type': 'post',
              'limit': 20,
              'order': 'createdAt'}
    return encode_url(url, params)

запросы на получение данных:

uid='5bd2b8b25188252a784d19d7'
device_id='1567748420039'
token='eyJhY2Nlc3NfdG9rZW4iOiJTTHVPcVRGBseWdTZHF4IiwicmVmcmVzaF90b2tlbiI6ImJHZkJDVDlWQkZiQUNMdTYiLCJ0b2tlbl90eXBlIjoibWFjIiwiZXhwaXJlX2luIjoyNTkyMDAwfQ%3D%3D'

url = get_juejin_url(uid, device_id, token)

headers = {
    'Origin': 'https://juejin.cn',
    'Referer': 'https://juejin.cn/user/958429870432461',
    'Sec-Fetch-Mode': 'cors',
    'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Mobile Safari/537.36'
}

res = requests.get(url, headers=headers)

if res.status_code == 200:
    json_data = res.json()
else:
    print('数据获取失败,请检查token是否失效')

4. Проанализируйте данные

4.1 Проанализируйте данные json, чтобы найти поле со списком статей

for k, v in json_data.items():
        print(k, ':', v)

вывод:

s : 1
m : ok
d : {'total': 11, 'entrylist': [{'collectionCount': 1, 'userRankIndex': 1.3086902928294, 'buildTime': 1568185450.1271, 'commentsCount': 0, 'gfw': False, 'objectId': '5d7832be6fb9a06ad4516f67', 'checkStatus': True, 'isEvent': False, ...

4.2 Проанализируйте одну статью, чтобы найти области интересов

article_list = json_data['d']['entrylist']
article = article_list[0]

article['title'], article['viewsCount'], article['rankIndex'], article['createdAt']

вывод:

('python 科学计算的基石 numpy(一)', 57, 0.49695221772782, '2019-09-10T23:33:19.013Z')

Извлечь поле интереса:

interest_list = [(article['title'], article['viewsCount'], article['rankIndex'], article['createdAt']) for article in article_list]

Просмотр извлеченных данных:

print('{}\t{}\t{}\t{}'.format('createdAt', 'rankIndex', 'viewsCount', 'title'))
for title, viewsCount, rankIndex, createdAt in interest_list:
    print('{}\t{}\t{}\t{}'.format(createdAt.split('T')[0], round(rankIndex, 10), viewsCount, title))

вывод:

createdAt	rankIndex	viewsCount	title
2019-09-10	0.4969522177	57	python 科学计算的基石 numpy(一)
2019-09-10	0.064785953	115	python 数据分析工具包 pandas(一)
2019-09-09	0.0265007422	108	OpenCv-Python 开源计算机视觉库 (一)
2019-09-08	0.0063690043	31	python 数据可视化工具包 matplotlib
2019-09-07	0.0078304184	104	python 图像处理类库 PIL (二)
2019-09-06	0.0021220196	10	python 标准库:os
2019-09-06	0.0025458508	26	python 图像处理类库 PIL (一)
2019-09-06	0.0073875365	144	python 标准库:random
2019-09-06	0.0013268195	6	jpeg 图像存储数据格式
2019-09-06	0.0079665762	6	python 内置函数
2019-09-06	0.0015289955	8	jupyter notebook 安装 C/C++ kernel

4.3 анализ данных панд

4.3.1 Создание объекта DataFrame

Создайте:

df = pd.DataFrame(interest_list, columns=['title', 'viewsCount', 'rankIndex', 'createdAt'])

Сортировать по объему чтения в порядке убывания:

df_sort_desc = df.sort_values('viewsCount', ascending=False).reset_index(drop=True)

df_sort_desc
title viewsCount rankIndex createdAt
0 Стандартная библиотека Python: случайный 144 0.007388 2019-09-06T06:09:08.408Z
1 Набор инструментов для анализа данных Python pandas (1) 115 0.064786 2019-09-10T07:37:53.507Z
2 OpenCv-Python Библиотека компьютерного зрения с открытым исходным кодом (1) 108 0.026501 2019-09-09T06:18:14.059Z
3 библиотека обработки изображений Python PIL (2) 104 0.007830 2019-09-07T11:25:48.391Z
4 Краеугольный камень научных вычислений Python numpy (1) 57 0.496952 2019-09-10T23:33:19.013Z
5 набор инструментов для визуализации данных python matplotlib 31 0.006369 2019-09-08T09:29:00.172Z
6 Библиотека обработки изображений Python PIL (1) 26 0.002546 2019-09-06T06:10:48.300Z
7 стандартная библиотека python: os 10 0.002122 2019-09-06T11:06:17.881Z
8 Блокнот jupyter устанавливает ядро ​​C/C++ 8 0.001529 2019-09-06T06:00:19.673Z
9 формат данных для хранения изображений jpeg 6 0.001327 2019-09-06T06:07:25.442Z
10 встроенные функции питона 6 0.007967 2019-09-06T06:04:26.794Z

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

fig, axes = plt.subplots(2, 1, figsize=(10, 10))

plt.subplots_adjust(wspace=0.5, hspace=0.5)

df = df.sort_values('viewsCount')

df.plot(subplots=True, ax=axes[0], x='title', y='viewsCount', kind='barh', legend=False)

df.plot(subplots=True, ax=axes[1], labels=df['title'], y='viewsCount', kind='pie', legend=False, labeldistance=1.2)

plt.subplots_adjust(left=0.3)
plt.show()

5. Сохраните данные

5.1 Сохранить в CSV-файл

import time

filename = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime())

#  保存 csv 文件
csv_file = filename + '.csv'
df.to_csv(csv_file, index=False)

5.2 Сохранить в файл Excel

# 保存 excel 文件
excel_file = filename + '.xls'
sheet_name = time.strftime("%Y-%m-%d", time.localtime())
df.to_excel(excel_file, sheet_name=sheet_name, index=False)

6. Запустить из командной строки

6.1 Инкапсуляция кода

Сохраните следующий код в файлcrawl_juejin.py:

#!/usr/local/bin/python

import requests
import pandas as pd
import matplotlib.pyplot as plt
import time
import argparse

headers = {
    'Origin': 'https://juejin.cn',
    'Referer': 'https://juejin.cn/user/958429870432461',
    'Sec-Fetch-Mode': 'cors',
    'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Mobile Safari/537.36'
}

def anlysis_by_url(url):
    res = requests.get(url, headers=headers)
    print("\ncrawl posts data on juejin.\n-----------\nget posts from {} ...\n".format(url))
    if res.status_code != 200:
        print('数据获取失败,请检查token是否失效')
        return

    json_data = res.json()

    article_list = json_data['d']['entrylist']
    total = json_data['d']['total']
    print('got {} posts.\n'.format(total))
    interest_list = [(article['title'], article['viewsCount'], article['rankIndex'], article['createdAt'])
                     for article in article_list]
    df = pd.DataFrame(interest_list, columns=['title', 'viewsCount', 'rankIndex', 'createdAt'])
    df_sort_desc = df.sort_values('viewsCount', ascending=False).reset_index(drop=True)
    
    print('data visualization ...\n')
    fig, axes = plt.subplots(2, 1, figsize=(10, 10))

    plt.subplots_adjust(wspace=0.5, hspace=0.5)

    df = df.sort_values('viewsCount')

    df.plot(subplots=True, ax=axes[0], x='title', y='viewsCount', kind='barh', legend=False)

    df.plot(subplots=True, ax=axes[1], labels=df['title'], y='viewsCount', kind='pie', legend=False, labeldistance=1.2)

    plt.subplots_adjust(left=0.3)
    plt.show()

    filename = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime())
    #  保存 csv 文件
    csv_file = filename + '.csv'
    df_sort_desc.to_csv(csv_file, index=False)
    print("saved to {}.\n".format(csv_file))
    # 保存 excel 文件
    excel_file = filename + '.xls'
    sheet_name = time.strftime("%Y-%m-%d", time.localtime())
    df_sort_desc.to_excel(excel_file, sheet_name=sheet_name, index=False)
    print("saved to {}.\n".format(excel_file))
    print("\n-----------\npersonal website: https://kenblog.top\njuejin: https://juejin.cn/user/958429870432461")

def get_cli_args():
    juejin_zhuanlan_api_full_url = 'https://timeline-merger-ms.juejin.im/v1/get_entry_by_self?src=web&uid=5bd2b8b25188252a784d19d7&device_id=1567748420039&token=eyJhY2Nlc3NfdG9rZW4iOiJTTHVPcVRGQ1BseWdTZHF4IiwicmVmcmVzaF90b2tlbiI6ImJHZkJDVDlWQkZiQUNMdTYiLCJ0b2tlbl90eXBlIjoibWFjIiwiZXhwaXJlX2luIjoyNTkyMDAwfQ%3D%3D&targetUid=5bd2b8b25188252a784d19d7&type=post&limit=20&order=createdAt'
    parser = argparse.ArgumentParser()
    parser.add_argument('-u', '--url', type=str, default=juejin_zhuanlan_api_full_url, help='URL')
    args = parser.parse_args()
    return args

if __name__ == '__main__':
    args = get_cli_args()
    anlysis_by_url(args.url)

6.2 Работа с командной строкой

в соответствии с2.1Представьте метод поиска URL-адреса интерфейса вашего собственного столбца. В форме:

https://timeline-merger-ms.juejin.im/v1/get_entry_by_self?src=web&uid=5bd2b8b25188252a784d19d7&device_id=1567748420039&token=eyJhY2Nlc3NfdG9rZW4iOiJTTHVPcVRGeWdTZHF4IiwicmVmcmVzaF90b2tlbiI6ImJHZkJDVDlWQkZiQUNMdTYiLCJ0b2tlbl90eXBlIjoibWFjIiwiZXhwaXJlX2luIjoyNTkyMDAwfQ%3D%3D&targetUid=5bd2b8b25188252a784d19d7&type=post&limit=20&order=createdAt

Выше приведен собственный URL автора. Если вы не укажете параметр url, этот адрес будет использоваться по умолчанию, но он используется только для проверки корректной работы скрипта, рекомендуется использовать свой собственный.

python crawl_juejin.py --url "https://timeline-merger-ms.juejin.im..."

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

Вам также может понравиться


Нелегко настаивать на написании колонки. Если вы считаете, что эта статья полезна для вас, не забудьте поставить лайк. Спасибо за поддержку!


Отсканируйте QR-код в WeChat, чтобы получить оригиналы новейших технологий