Wir fördern die Qiita-Artikelausgabeaktivitäten innerhalb des Unternehmens. Das ist G-awa. Die Output-Lernmethode weist eine gute Lerneffizienz auf und wird dringend empfohlen. Auf der anderen Seite ist es jedoch schwierig, alleine weiterzumachen. Daher ist es wichtig, dass Teams und Organisationen sich gegenseitig unterstützen. Es ist leicht, dein Herz zu brechen, wenn du allein bist.
→→→→
Ich habe den gestrigen Artikel gelesen, er war sehr hilfreich: thumbsup: Eine Umgebung, in der Sie sich gegenseitig ermutigen können, ist beispielsweise eine großartige Umgebung für Ingenieure, um zu wachsen. Wir möchten eine so wunderbare Umgebung schaffen, indem wir einen Kanal erstellen und betreiben, an dem Personen, die auf Qiita posten, teilnehmen (tatsächlich handelt es sich um einen öffentlichen Kanal, den alle Mitarbeiter anzeigen und veröffentlichen können).
Beim Aufbau und Betrieb der Qiita-Organisation stehen wir vor den folgenden Herausforderungen.
――Ich möchte nicht die tägliche Leistung aller verpassen
Also habe ich ein Tool erstellt, um den Chat über die Update-Informationen des Artikels zu informieren.
Es ist ein Tool, das neue Artikel abruft, die an die Qiita-Organisation gesendet wurden, und Rocket Chat benachrichtigt. Da die Qiita-API die Organisationsinformationen nicht abrufen konnte, wird sie durch Crawlen implementiert. Es läuft cron auf Lambda auf AWS.
Technologie-Stack | Erläuterung |
---|---|
AWS Lambda | Ausführungsumgebung |
Serverless Framework | Bereitstellen |
Python beautiful soup | Krabbeln |
rocket chat api | Poste eine Nachricht an Rocket Chat |
CircleCI | Prüfung |
Klicken Sie hier für den Quellcode https://github.com/qiita-scraper/qiita-scraper-rocket-chat
Verwenden Sie schöne Suppe zum Crawlen. Ich möchte auch das Buchungsdatum extrahieren, also mache ich eine kleine lästige Sache. Nein, Krabbeln ist hart.
def fetch_recent_user_articles(self, user):
"""
Erhalten Sie mehrere aktuelle Qiita-Artikel, die vom angegebenen Benutzer veröffentlicht wurden
:param user:
:return:
"""
qiita_url = 'https://qiita.com/' + user
response = request.urlopen(qiita_url)
soup = BeautifulSoup(response, 'html.parser')
response.close()
created_ats = []
created_dates = soup.find_all('div', class_='ItemLink__info')
for created_date in created_dates:
div = re.sub('<a.*?>|</a>', '', str(created_date))
text = re.sub('<div.*?>|</div>', '', div).split()
month = str(time.strptime(text[3], '%b').tm_mon)
day = text[4][:-1]
year = text[5]
created_at = year + '/' + month + '/' + day
created_ats.append(created_at)
articles = []
a_tags = soup.find_all('a', class_='u-link-no-underline')
for index, a in enumerate(a_tags):
href = a.get('href')
url = 'https://qiita.com' + href
title = a.string
articles.append({'title': title, 'url': url, 'created_at': created_ats[index]})
return articles
RocketChat veröffentlicht API-Spezifikationen. https://rocket.chat/docs/developer-guides/rest-api/
Verwenden Sie einfach urllib, die Standard-Python-Bibliothek. Der Artikel urllib.request ist ausreichend für Python-HTTP-Client war hilfreich. Wirklich Urllib ist genug.
Melden Sie sich an, um das authToken und die Benutzer-ID abzurufen. Es wird durch Schreiben in den http-Header authentifiziert und greift auf andere APIs zu.
def __login_rocket_chat(self, user, password):
"""
Melden Sie sich bei Rocket Chat an und authentifizieren Sie sich_Token und Benutzer_Holen Sie sich die ID.
:param url:
:return:
"""
obj = {
"user": user,
"password": password
}
json_data = json.dumps(obj).encode("utf-8")
headers = {"Content-Type": "application/json"}
req_object = request.Request(self.url + '/api/v1/login', data=json_data, headers=headers, method='POST')
with request.urlopen(req_object) as response:
response_body = response.read().decode("utf-8")
result_objs = json.loads(response_body.split('\n')[0])
user_id = result_objs["data"]["userId"]
auth_token = result_objs["data"]["authToken"]
print(user_id, auth_token)
return auth_token, user_id
Suchen Sie nach der ID des Chatrooms nach Namen.
def fetch_room_id(self, room_name):
"""
Rocket Chatraum_Holen Sie sich die ID.
:param room_name:
:return:
"""
headers = {
"Content-Type": "application/json",
"X-Auth-Token": self.auth_token,
"X-User-Id": self.user_id
}
params = {'roomName': room_name}
url = '{}?{}'.format(self.url + '/api/v1/channels.info', parse.urlencode(params))
req_object = request.Request(url, headers=headers, method="GET")
with request.urlopen(req_object) as response:
response_body = response.read().decode("utf-8")
print(response_body)
result_objs = json.loads(response_body.split('\n')[0])
channel = result_objs.get('channel')
return channel.get('_id')
Sende eine Nachricht. Sie können nicht senden, indem Sie den Benutzernamen und das Symbolbild vom RocketChat-Webbildschirm ersetzen, aber Sie können senden, indem Sie es von der API ersetzen. Es ist ein bisschen knifflig, nicht wahr?
def send_message_to_rocket_chat(self, msg, room_name):
"""
Senden Sie eine Nachricht an Rocket Chat
:param msg:
:param room_name
:return:
"""
headers = {
"Content-Type": "application/json",
"X-Auth-Token": self.auth_token,
"X-User-Id": self.user_id
}
print(headers)
body = {
"message": {
"rid": self.fetch_room_id(room_name),
"msg": msg,
"alias": 'Qiita Bot',
"avatar": 'https://haskell.jp/antenna/image/logo/qiita.png'
}
}
print(body)
req_object = request.Request(self.url + '/api/v1/chat.sendMessage', data=json.dumps(body).encode("utf-8"), headers=headers, method="POST")
with request.urlopen(req_object) as response:
So was.
Führen Sie den Test aus, indem Sie RocketChat und mongoDB im Docker starten und eine Anfrage an die eigentliche RocketChat-Anwendung senden. Es tut mir leid, Qiita, ich greife auf die reale Sache zu und teste sie.
Starten Sie RocketChat mit Docker-Compose. https://rocket.chat/docs/installation/docker-containers/docker-compose/
Es scheint, dass Sie den nervigen Assistentenbildschirm beim Starten von RocketChat überspringen können, indem Sie OVERWRITE_SETTING_Show_Setup_Wizard = complete als Umgebungsvariable angeben. Referenz: https://github.com/RocketChat/Rocket.Chat/issues/2233
docker-compose.yml
version: "2"
services:
rocketchat:
image: rocketchat/rocket.chat:latest
command: >
bash -c
"for i in `seq 1 30`; do
node main.js &&
s=$$? && break || s=$$?;
echo \"Tried $$i times. Waiting 5 secs...\";
sleep 5;
done; (exit $$s)"
restart: unless-stopped
volumes:
- ./uploads:/app/uploads
environment:
- PORT=3000
- ROOT_URL=http://localhost:3000
- MONGO_URL=mongodb://mongo:27017/rocketchat
- MONGO_OPLOG_URL=mongodb://mongo:27017/local
- MAIL_URL=smtp://smtp.email
- ADMIN_USERNAME=admin
- ADMIN_PASS=supersecret
- [email protected]
# https://github.com/RocketChat/Rocket.Chat/issues/2233
- OVERWRITE_SETTING_Show_Setup_Wizard=completed
depends_on:
- mongo
ports:
- 3000:3000
labels:
- "traefik.backend=rocketchat"
- "traefik.frontend.rule=Host: your.domain.tld"
mongo:
image: mongo:4.0
restart: unless-stopped
volumes:
- ./data/db:/data/db
command: mongod --smallfiles --oplogSize 128 --replSet rs0 --storageEngine=mmapv1
labels:
- "traefik.enable=false"
# this container's job is just run the command to initialize the replica set.
# it will run the command and remove himself (it will not stay running)
mongo-init-replica:
image: mongo:4.0
command: >
bash -c
"for i in `seq 1 30`; do
mongo mongo/rocketchat --eval \"
rs.initiate({
_id: 'rs0',
members: [ { _id: 0, host: 'localhost:27017' } ]})\" &&
s=$$? && break || s=$$?;
echo \"Tried $$i times. Waiting 5 secs...\";
sleep 5;
done; (exit $$s)"
depends_on:
- mongo
Führen Sie dann den Test mit RocketChat aus, das bei localhost: 3000 mit Pythons Unittest gestartet wurde. Es ist einfach.
import unittest
from rocket_chat.rocket_chat import RocketChat
import urllib
from qiita.qiita import Qiita
import freezegun
import json
class TestQiitaScraper(unittest.TestCase):
def setUp(self):
# rocket chat admin user set in docker-compoose.yml rocketchat service environment value.
self.aurhorized_user = 'admin'
self.aurhorized_password = 'supersecret'
self.rocket_chat_url = 'http://localhost:3000'
def test_login_success(self):
rocket_chat = RocketChat(self.rocket_chat_url, self.aurhorized_user, self.aurhorized_password)
self.assertNotEqual(len(rocket_chat.auth_token), 0)
self.assertNotEqual(len(rocket_chat.user_id), 0)
def test_login_failed(self):
with self.assertRaises(urllib.error.HTTPError):
unauthorized_user = 'mbvdr678ijhvbjiutrdvbhjutrdfyuijhgf'
unauthorized_pass = 'gfr67865tghjgfr567uijhfrt67ujhgthhh'
RocketChat(self.rocket_chat_url, unauthorized_user, unauthorized_pass)
Geben Sie "machine" für "executer" anstelle von "imagae" an, um Docker-Compose in der Circleci-Ausführungsumgebung zu verwenden. * Die Cache-Einstellungen sind der Einfachheit halber ausgeschlossen.
.circleci/config.yml
version: 2
jobs:
build:
machine:
image: circleci/classic:201808-01
steps:
- checkout
- run:
name: "Switch to Python v3.7"
command: |
pyenv versions
pyenv global 3.7.0
- run:
name: docker-compose up
command: sh dcup.sh
- run:
name: install dependencies and test
command: |
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt
pip install -r requirements-dev.txt
python -m unittest test.py
Ich bin vom Wesentlichen abgehoben (Förderung der Ausgabeaktivitäten der internen Organisation), aber ich habe gelernt, wie man kontinuierlich mit Crawlen und Docker-Compose testet. Es war. Ich hoffe, dass dies die Lerneffizienz der Organisation noch ein wenig verbessern wird.
Recommended Posts