Урок стъпка по стъпка с наличен пълен изходен код.

Да знаете как да търсите данни в мрежата е страхотно и помага да отворите много врати, но данните се променят и могат да остареят много бързо. Така че научаването как автоматично да получавате най-новите данни също е от решаващо значение.

Мотивация

Наскоро разработих stocksymbol, пакет на Python, който съдържа списък с борсови символи от всички големи фондови борси в различни региони и пазари.



Както можете да си представите, списъкът със символи на акции непрекъснато се променя и трябва да намеря начин да го поддържам актуализиран. Благодарение на GitHub Actions, който е напълно интегриран в GitHub, мога да изпълня тази задача доста лесно и е напълно безплатно.

В тази статия ще споделя прост урок, който засяга следните теми:

  1. Уеб скрапинг с помощта на Python
  2. Съхраняване на данни в MongoDB
  3. Планирайте и автоматизирайте процеса с помощта на GitHub Actions

Предпоставка

  1. GitHub акаунт за хостване на нашия код и изпълнение на GitHub Actions

GitHub Actions е инструмент за автоматизиране на работни потоци и е безплатен до квота от 2000 минути на потребител на месец. Научете повече за действията на GitHub тук.

2. MongoDB акаунт (по избор)

MongoDB е популярна NoSQL база данни, базирана на облак. Има доста добро безплатно ниво и не е необходима инсталация. Научете повече за Python и MongoDB тук.

Част 1: Извличане на данни

Един от най-широко използваните набори от данни в света на търговията може да бъде „списъкът на компаниите от S&P 500“. В част 1 основният ни фокус е да изтрием данните от уебсайтове, които съдържат списъка. За да бъдем прости, ще използваме списъка, намерен в Wikipedia.

Нека започнем със създаване на файл, наречен automate_web_scraping.py в нашата папка на проекта и това е очертанието на кодовете, които ще напишем.

(project_folder/automate_web_scraping.py)
# import packages
# scrape the list of S&P 500 companies
# save to local csv file
# push symbol list to MongoDB

Както обикновено, първо, нека импортираме пакетите, които ще използваме.

# import packages
import pandas as pd

Pandasима aread_html() метод, който може да чете HTML таблици в списък с DataFrame обекти, което е точно това, от което се нуждаем в този случай.

# scrape the list of S&P 500 companies
url = https://en.wikipedia.org/wiki/List_of_S%26P_500_companies'
payload = pd.read_html(url)
symbol_list = payload[0]

И отпечатването наsymbol_list ни дава:

Това е всичко за част 1!

Толкова просто. Разбира се, това е може би най-простият пример за уеб скрапинг, но тъй като основната ни цел е частта за автоматизация, този пример трябва да е достатъчен.

Част 2: Съхраняване на данни

След като успеем да получим данните онлайн, нека се опитаме да запазим данните. Ще демонстрирам как да го съхраня в локален файл и още по-добре в онлайн база данни, в този случай MongoDB.

За да запазите списъка със символи в локален CSV файл, просто използвайте метода to_csv() така:

# save to local csv file
symbol_list.to_csv('SAP500_symbol_list.csv')

Ето как ще изглежда запазеният CSV файл.

След това нека да преминем към съхраняване на данни в MongoDB. За тези, които не се интересуват от тази част, можете да преминете към Част 3: Автоматизация.

2.1 Създайте клъстер от база данни

Изберете безплатния споделен клъстер.

Изберете облачен доставчик и регион и щракнете върху Създаване на клъстер. Налични са много безплатни опции.

Изчакайте вашият клъстер да бъде създаден. Завършването може да отнеме няколко минути.

2.2 Свързване към клъстер

За нашия пример изберете Разрешаване на достъп от всяко място.

Създайте потребител на база данни, за да разрешите достъп от нашето приложение. Запазете паролата за по-късно.

След това изберете метод на свързване.

Изберете драйвер и версия. В този случай Python и „3.6 или по-нова версия“. Копирайте низа за връзка и го запазете някъде за по-късна употреба.

2.3 Свързване от клиентски код на Python

След това сме готови да се свържем с MongoDB от нашия Python скрипт. Първо, трябва да инсталираме още 2 пакета, за да позволим връзка с MongoDB.

# install MongoDB related packages
pip install pymongo
pip install dnspython

Сега можем да се свържем с MongoDB клъстера, който току-що създадохме, като използваме низа за връзка, който копирахме по-рано.

# import MongoClient from pymongo
from pymongo import MongoClient
# establish a client connection
MONGODB_CONNECTION_STRING = "<Your Connection String Here>"
client = MongoClient(MONGODB_CONNECTION_STRING)

За да проверим дали връзката е установена без проблем, можем да направим следното:

# to check if connection has been established
client.server_info()['ok']

Ако всичко е наред, сега можем да продължим да изпращаме данни към MongoDB. Първо, преобразуваме списъка със символи, който получихме по-рано от DataFrame, в речник.

След това можем да посочим колекция (можете да я разглеждате като таблица в SQL база данни) в нашия DB клъстер. В този случай, тъй като просто презаписваме списъка със символи в колекцията, можем просто да изпразним колекцията и да вмъкнем нови записи, използвайки drop() иinsert_many() методи.

# convert to dictionary for uploading to MongoDB
symbol_dict = symbol_list.to_dict('records')
# point to symbolsDB collection 
db = client.symbolsDB
# emtpy symbols collection before inserting new records
db.symbols.drop()
# insert new symbols
db.symbols.insert_many(symbol_dict)

Ако всичко върви добре, сега би трябвало да можем да направим запитване към списъка със символи от базата данни.

Разбира се, ако отидем на таблото за управление на MongoDB, трябва да можем да видим, че сега има 504 документа в колекциятаsymbols.

Сега нашият код трябва да изглежда така. Можете също да изпробвате кодовете с помощта на този демонстрационен бележник.

Част 3: Автоматизация с помощта на GitHub Actions

Страхотен! Вече сме в състояние да изчерпим онлайн списък с компании от S&P 500 и да го съхраним в облачна база данни. Тук идва най-важната част от този урок, която е да автоматизирате процеса с помощта на GitHub Actions.

Можем да дефинираме работен поток, по същество набор от инструкции, като използваме YAML файл, наречен update-dabase.yml, намиращ се в папката /.github/workflows.

Първото нещо, което трябва да направим, е да дадем име на нашия работен процес и да добавим графика, по който искаме да работи, да речем веднъж на месец.

(project_folder/.github/workflows/update-database.yml)
name: Update S&P500 Symbol List
on:
  schedule:
    - cron: '0 0 1 * *'
  workflow_dispatch:

Ако не сте запознати сcronизраза, можете да научите повече за него тук, но cron:'0 0 1 * *' основно означава „в минута 0 час 0 на първия ден от месеца“. Освен това добавянето на workflow_dispatch ни позволява да изпълняваме работния процес ръчно в раздела Действия на GitHub.

Сега трябва да изброим конкретните стъпки или задачи, които искаме да изпълним в нашия работен процес. Започваме със създаване на група, нареченаupdate_symbol_list, която ще работи на най-новата версия на Ubuntu runner.

Първата задача, която трябва да изпълним, е плащане към нашето хранилище, което може да се направи с вградено действие, наречено actions/checkout@v2.

jobs:
  update_symbol_list:
    name: Update S&P500 symbol list periodically
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

След това трябва да настроим Python на виртуалната машина, като използваме друго вградено действие, наречено actions/setup-python@v2и указвайки версията на Python и задавайки pip като кеш за кеширане на зависимости.

- name: Setup Python
  uses: actions/setup-python@v2
  with:
    python-version: '3.7'
    cache: 'pip'

Преди да продължим, тъй като GitHub Actions ще изпълни нашия скрипт на виртуална машина, трябва да го уведомим какви са зависимостите на нашата програма, като добавим arequirements.txt в основата на нашата папка на проекта.

(project_folder/requirement.txt)
pymongo==4.1.1
dnspython==2.2.1
pandas==1.3.5

Сега можем да инструктираме работния процес да инсталира нашите зависимости от requirements.txt.

- name: Install Dependencies
  run: pip install -r requirements.txt

След това е време да стартирате основния скрипт. Преди това, помните ли, че имахме константа, наречена MONGODB_CONNECTION_STRING в нашия код по-рано? Не е добра практика да оставяме нашия низ за свързване, който съдържа някаква чувствителна информация, публичен. Вместо това трябва да го заменим със секретна стойност, която по-късно можем да конфигурираме в GitHub.

За да предадем тайната на основния скрипт на Python, можем да създадем променлива на средата, използвайки свойството env като следното:

- name: Run Script
  env: MONGODB_CONNECTION_STRING: ${{ secrets.MONGODB_CONNECTION_STRING }}
  run: |
    python automate_web_scraping.py

И така, обратно в нашия основен automate_web_scraping.py скрипт, трябва да вземем низа за свързване, съхранен като променлива на средата, и да го използваме, за да се свържем с MongoDB. Следователно, ред 16 в основния файл трябва да бъде променен на:

(project_folder/automate_web_scraping.py)
...
MONGODB_CONNECTION_STRING = os.environ['MONGODB_CONNECTION_STRING']
...

Освен това трябва да импортираме и пакетаos. Сега крайният код на основния файл трябва да бъде като това.

Сега преместваме фокуса си обратно към нашия YAML файл с работен поток. Остава само едно последно нещо, което трябва да добавите, което е да ангажирате и да изпратите промените в CSV файла в нашето хранилище.

- name: Commit and Push Changes
  run: |
    git config --local user.email "[email protected]"
    git config --local user.name "GitHub Actions"
    git add S&P500_symbol_list.csv
    git commit -m "Updated symbol list on `date` with GitHub Actions" || echo "No Changes to Commit"
    git push origin master || echo "No Changes to Commit"

Събирайки всичко заедно, нашият окончателен YAML файл трябва да изглежда така:

Сега нека преместим нашата локална папка в отдалечено хранилище на GitHub и да оставим магията да се случи. За да направим това, трябва да създадем ново хранилище на GitHub и да следваме стъпките тук или да използваме следния код.

git init
git add .
git commit -m 'Added automatic scraping script'
git remote add origin <REMOTE_URL>
git push -u origin master

Не на последно място, не забравяйте да добавите тайна на хранилище с името MONGODB_CONNECTION_STRINGпод Настройки.

За демонстрационни цели промених графика на cron на всеки 5 минути и ако преминем към раздела Действия, можем да видим, че работният процес, който сме дефинирали в YAML файла, е изпълняван няколко пъти, но не на всеки 5 минути.

Това е така, защото понякога има забавяне при задействане на GitHub Actions.

Много пъти има забавяне при задействане на планирания работен поток.
Обикновено времето на забавяне е около 3 до 10 минути
.

Въпреки това GitHub Actions обикновено върши работата си правилно и аз съм много доволен от него.

Заключение

В този урок засегнахме следното:

  1. Уеб скрапинг с помощта на Python
  2. Съхраняване на данните в облачна база данни (MongoDB)
  3. Планирайте и автоматизирайте процеса с помощта на GitHub Actions

Използвах някои доста ясни примери тук, но се надявам, че ви даде някои идеи за това какво можете да правите с Python, MongoDB и, разбира се, GitHub Actions.

Всички кодове по-горе могат да бъдат намерени тук в това хранилище на GitHub.

Създавам качествено съдържание и уроци за технически анализ на акции с помощта на Python. Ако ви харесва това, което виждате, и все още не сте абонирани за Medium, не се колебайте да го направите чрез връзката по-долу и да ме следвате по време на моето пътуване (част от таксата ще отиде директно при мен). Благодарим ви за подкрепата.



Повече съдържание в PlainEnglish.io. Регистрирайте се за нашия безплатен седмичен бюлетин. Следвайте ни в Twitter и LinkedIn. Присъединете се към нашата общност Discord.