项目:painting 主题
- 项目初始版本 - 项目默认主题 painting
44
.github/workflows/build-and-run.yml
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
name: Build and Run
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-run:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: 1. Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 2. Set up Python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
|
||||||
|
- name: 3. Install
|
||||||
|
run: |
|
||||||
|
pip install --upgrade pip
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
- name: 4. Run
|
||||||
|
run: |
|
||||||
|
python ./main.py &
|
||||||
|
sleep 7
|
||||||
|
|
||||||
|
- name: 5. Build
|
||||||
|
run: |
|
||||||
|
wget http://localhost:7777
|
||||||
|
|
||||||
|
- name: 6. Log
|
||||||
|
run: |
|
||||||
|
cat endofyear.log
|
||||||
|
|
||||||
|
- name: 7. Push static HTML
|
||||||
|
uses: peaceiris/actions-gh-pages@v3
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
publish_dir: ./static
|
||||||
|
publish_branch: html
|
24
.github/workflows/docker-publish.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
name: Publish Docker image
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
run: |
|
||||||
|
docker build -t sevenwate/endofyear:latest .
|
||||||
|
docker push sevenwate/endofyear:latest
|
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/.idea
|
||||||
|
*.log
|
||||||
|
/Pipfile
|
||||||
|
/Pipfile.lock
|
11
Dockerfile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
FROM python:3.11.0
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ADD . /app
|
||||||
|
|
||||||
|
RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple && pip install -r requirements.txt
|
||||||
|
|
||||||
|
EXPOSE 7777
|
||||||
|
|
||||||
|
CMD [ "python", "./main.py" ]
|
625
License
Normal file
@ -0,0 +1,625 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies of this license
|
||||||
|
document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for software and
|
||||||
|
other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed to take
|
||||||
|
away your freedom to share and change the works. By contrast, the GNU General
|
||||||
|
Public License is intended to guarantee your freedom to share and change all
|
||||||
|
versions of a program--to make sure it remains free software for all its users.
|
||||||
|
We, the Free Software Foundation, use the GNU General Public License for most
|
||||||
|
of our software; it applies also to any other work released this way by its
|
||||||
|
authors. You can apply it to your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not price. Our
|
||||||
|
General Public Licenses are designed to make sure that you have the freedom
|
||||||
|
to distribute copies of free software (and charge for them if you wish), that
|
||||||
|
you receive source code or can get it if you want it, that you can change
|
||||||
|
the software or use pieces of it in new free programs, and that you know you
|
||||||
|
can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you these rights
|
||||||
|
or asking you to surrender the rights. Therefore, you have certain responsibilities
|
||||||
|
if you distribute copies of the software, or if you modify it: responsibilities
|
||||||
|
to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether gratis or
|
||||||
|
for a fee, you must pass on to the recipients the same freedoms that you received.
|
||||||
|
You must make sure that they, too, receive or can get the source code. And
|
||||||
|
you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps: (1) assert
|
||||||
|
copyright on the software, and (2) offer you this License giving you legal
|
||||||
|
permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains that
|
||||||
|
there is no warranty for this free software. For both users' and authors'
|
||||||
|
sake, the GPL requires that modified versions be marked as changed, so that
|
||||||
|
their problems will not be attributed erroneously to authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run modified
|
||||||
|
versions of the software inside them, although the manufacturer can do so.
|
||||||
|
This is fundamentally incompatible with the aim of protecting users' freedom
|
||||||
|
to change the software. The systematic pattern of such abuse occurs in the
|
||||||
|
area of products for individuals to use, which is precisely where it is most
|
||||||
|
unacceptable. Therefore, we have designed this version of the GPL to prohibit
|
||||||
|
the practice for those products. If such problems arise substantially in other
|
||||||
|
domains, we stand ready to extend this provision to those domains in future
|
||||||
|
versions of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents. States
|
||||||
|
should not allow patents to restrict development and use of software on general-purpose
|
||||||
|
computers, but in those that do, we wish to avoid the special danger that
|
||||||
|
patents applied to a free program could make it effectively proprietary. To
|
||||||
|
prevent this, the GPL assures that patents cannot be used to render the program
|
||||||
|
non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and modification
|
||||||
|
follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of works,
|
||||||
|
such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this License.
|
||||||
|
Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals
|
||||||
|
or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work in
|
||||||
|
a fashion requiring copyright permission, other than the making of an exact
|
||||||
|
copy. The resulting work is called a "modified version" of the earlier work
|
||||||
|
or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based on the
|
||||||
|
Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without permission,
|
||||||
|
would make you directly or secondarily liable for infringement under applicable
|
||||||
|
copyright law, except executing it on a computer or modifying a private copy.
|
||||||
|
Propagation includes copying, distribution (with or without modification),
|
||||||
|
making available to the public, and in some countries other activities as
|
||||||
|
well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other parties
|
||||||
|
to make or receive copies. Mere interaction with a user through a computer
|
||||||
|
network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices" to the
|
||||||
|
extent that it includes a convenient and prominently visible feature that
|
||||||
|
(1) displays an appropriate copyright notice, and (2) tells the user that
|
||||||
|
there is no warranty for the work (except to the extent that warranties are
|
||||||
|
provided), that licensees may convey the work under this License, and how
|
||||||
|
to view a copy of this License. If the interface presents a list of user commands
|
||||||
|
or options, such as a menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work for making
|
||||||
|
modifications to it. "Object code" means any non-source form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official standard
|
||||||
|
defined by a recognized standards body, or, in the case of interfaces specified
|
||||||
|
for a particular programming language, one that is widely used among developers
|
||||||
|
working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other than
|
||||||
|
the work as a whole, that (a) is included in the normal form of packaging
|
||||||
|
a Major Component, but which is not part of that Major Component, and (b)
|
||||||
|
serves only to enable use of the work with that Major Component, or to implement
|
||||||
|
a Standard Interface for which an implementation is available to the public
|
||||||
|
in source code form. A "Major Component", in this context, means a major essential
|
||||||
|
component (kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to produce
|
||||||
|
the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all the source
|
||||||
|
code needed to generate, install, and (for an executable work) run the object
|
||||||
|
code and to modify the work, including scripts to control those activities.
|
||||||
|
However, it does not include the work's System Libraries, or general-purpose
|
||||||
|
tools or generally available free programs which are used unmodified in performing
|
||||||
|
those activities but which are not part of the work. For example, Corresponding
|
||||||
|
Source includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically linked
|
||||||
|
subprograms that the work is specifically designed to require, such as by
|
||||||
|
intimate data communication or control flow between those subprograms and
|
||||||
|
other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users can regenerate
|
||||||
|
automatically from other parts of the Corresponding Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of copyright
|
||||||
|
on the Program, and are irrevocable provided the stated conditions are met.
|
||||||
|
This License explicitly affirms your unlimited permission to run the unmodified
|
||||||
|
Program. The output from running a covered work is covered by this License
|
||||||
|
only if the output, given its content, constitutes a covered work. This License
|
||||||
|
acknowledges your rights of fair use or other equivalent, as provided by copyright
|
||||||
|
law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not convey, without
|
||||||
|
conditions so long as your license otherwise remains in force. You may convey
|
||||||
|
covered works to others for the sole purpose of having them make modifications
|
||||||
|
exclusively for you, or provide you with facilities for running those works,
|
||||||
|
provided that you comply with the terms of this License in conveying all material
|
||||||
|
for which you do not control copyright. Those thus making or running the covered
|
||||||
|
works for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of your copyrighted
|
||||||
|
material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under the conditions
|
||||||
|
stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological measure
|
||||||
|
under any applicable law fulfilling obligations under article 11 of the WIPO
|
||||||
|
copyright treaty adopted on 20 December 1996, or similar laws prohibiting
|
||||||
|
or restricting circumvention of such measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid circumvention
|
||||||
|
of technological measures to the extent such circumvention is effected by
|
||||||
|
exercising rights under this License with respect to the covered work, and
|
||||||
|
you disclaim any intention to limit operation or modification of the work
|
||||||
|
as a means of enforcing, against the work's users, your or third parties'
|
||||||
|
legal rights to forbid circumvention of technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you receive
|
||||||
|
it, in any medium, provided that you conspicuously and appropriately publish
|
||||||
|
on each copy an appropriate copyright notice; keep intact all notices stating
|
||||||
|
that this License and any non-permissive terms added in accord with section
|
||||||
|
7 apply to the code; keep intact all notices of the absence of any warranty;
|
||||||
|
and give all recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey, and you
|
||||||
|
may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to produce
|
||||||
|
it from the Program, in the form of source code under the terms of section
|
||||||
|
4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified it, and
|
||||||
|
giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is released under
|
||||||
|
this License and any conditions added under section 7. This requirement modifies
|
||||||
|
the requirement in section 4 to "keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this License to anyone
|
||||||
|
who comes into possession of a copy. This License will therefore apply, along
|
||||||
|
with any applicable section 7 additional terms, to the whole of the work,
|
||||||
|
and all its parts, regardless of how they are packaged. This License gives
|
||||||
|
no permission to license the work in any other way, but it does not invalidate
|
||||||
|
such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display Appropriate
|
||||||
|
Legal Notices; however, if the Program has interactive interfaces that do
|
||||||
|
not display Appropriate Legal Notices, your work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent works,
|
||||||
|
which are not by their nature extensions of the covered work, and which are
|
||||||
|
not combined with it such as to form a larger program, in or on a volume of
|
||||||
|
a storage or distribution medium, is called an "aggregate" if the compilation
|
||||||
|
and its resulting copyright are not used to limit the access or legal rights
|
||||||
|
of the compilation's users beyond what the individual works permit. Inclusion
|
||||||
|
of a covered work in an aggregate does not cause this License to apply to
|
||||||
|
the other parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms of sections
|
||||||
|
4 and 5, provided that you also convey the machine-readable Corresponding
|
||||||
|
Source under the terms of this License, in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product (including
|
||||||
|
a physical distribution medium), accompanied by the Corresponding Source fixed
|
||||||
|
on a durable physical medium customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product (including
|
||||||
|
a physical distribution medium), accompanied by a written offer, valid for
|
||||||
|
at least three years and valid for as long as you offer spare parts or customer
|
||||||
|
support for that product model, to give anyone who possesses the object code
|
||||||
|
either (1) a copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical medium customarily
|
||||||
|
used for software interchange, for a price no more than your reasonable cost
|
||||||
|
of physically performing this conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the written
|
||||||
|
offer to provide the Corresponding Source. This alternative is allowed only
|
||||||
|
occasionally and noncommercially, and only if you received the object code
|
||||||
|
with such an offer, in accord with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated place (gratis
|
||||||
|
or for a charge), and offer equivalent access to the Corresponding Source
|
||||||
|
in the same way through the same place at no further charge. You need not
|
||||||
|
require recipients to copy the Corresponding Source along with the object
|
||||||
|
code. If the place to copy the object code is a network server, the Corresponding
|
||||||
|
Source may be on a different server (operated by you or a third party) that
|
||||||
|
supports equivalent copying facilities, provided you maintain clear directions
|
||||||
|
next to the object code saying where to find the Corresponding Source. Regardless
|
||||||
|
of what server hosts the Corresponding Source, you remain obligated to ensure
|
||||||
|
that it is available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided you inform
|
||||||
|
other peers where the object code and Corresponding Source of the work are
|
||||||
|
being offered to the general public at no charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded from
|
||||||
|
the Corresponding Source as a System Library, need not be included in conveying
|
||||||
|
the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any tangible
|
||||||
|
personal property which is normally used for personal, family, or household
|
||||||
|
purposes, or (2) anything designed or sold for incorporation into a dwelling.
|
||||||
|
In determining whether a product is a consumer product, doubtful cases shall
|
||||||
|
be resolved in favor of coverage. For a particular product received by a particular
|
||||||
|
user, "normally used" refers to a typical or common use of that class of product,
|
||||||
|
regardless of the status of the particular user or of the way in which the
|
||||||
|
particular user actually uses, or expects or is expected to use, the product.
|
||||||
|
A product is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent the
|
||||||
|
only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods, procedures,
|
||||||
|
authorization keys, or other information required to install and execute modified
|
||||||
|
versions of a covered work in that User Product from a modified version of
|
||||||
|
its Corresponding Source. The information must suffice to ensure that the
|
||||||
|
continued functioning of the modified object code is in no case prevented
|
||||||
|
or interfered with solely because modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or specifically
|
||||||
|
for use in, a User Product, and the conveying occurs as part of a transaction
|
||||||
|
in which the right of possession and use of the User Product is transferred
|
||||||
|
to the recipient in perpetuity or for a fixed term (regardless of how the
|
||||||
|
transaction is characterized), the Corresponding Source conveyed under this
|
||||||
|
section must be accompanied by the Installation Information. But this requirement
|
||||||
|
does not apply if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has been installed
|
||||||
|
in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a requirement
|
||||||
|
to continue to provide support service, warranty, or updates for a work that
|
||||||
|
has been modified or installed by the recipient, or for the User Product in
|
||||||
|
which it has been modified or installed. Access to a network may be denied
|
||||||
|
when the modification itself materially and adversely affects the operation
|
||||||
|
of the network or violates the rules and protocols for communication across
|
||||||
|
the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided, in accord
|
||||||
|
with this section must be in a format that is publicly documented (and with
|
||||||
|
an implementation available to the public in source code form), and must require
|
||||||
|
no special password or key for unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this License
|
||||||
|
by making exceptions from one or more of its conditions. Additional permissions
|
||||||
|
that are applicable to the entire Program shall be treated as though they
|
||||||
|
were included in this License, to the extent that they are valid under applicable
|
||||||
|
law. If additional permissions apply only to part of the Program, that part
|
||||||
|
may be used separately under those permissions, but the entire Program remains
|
||||||
|
governed by this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option remove any
|
||||||
|
additional permissions from that copy, or from any part of it. (Additional
|
||||||
|
permissions may be written to require their own removal in certain cases when
|
||||||
|
you modify the work.) You may place additional permissions on material, added
|
||||||
|
by you to a covered work, for which you have or can give appropriate copyright
|
||||||
|
permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you add
|
||||||
|
to a covered work, you may (if authorized by the copyright holders of that
|
||||||
|
material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the terms of
|
||||||
|
sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or author
|
||||||
|
attributions in that material or in the Appropriate Legal Notices displayed
|
||||||
|
by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or requiring
|
||||||
|
that modified versions of such material be marked in reasonable ways as different
|
||||||
|
from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or authors
|
||||||
|
of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some trade names,
|
||||||
|
trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that material by
|
||||||
|
anyone who conveys the material (or modified versions of it) with contractual
|
||||||
|
assumptions of liability to the recipient, for any liability that these contractual
|
||||||
|
assumptions directly impose on those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further restrictions"
|
||||||
|
within the meaning of section 10. If the Program as you received it, or any
|
||||||
|
part of it, contains a notice stating that it is governed by this License
|
||||||
|
along with a term that is a further restriction, you may remove that term.
|
||||||
|
If a license document contains a further restriction but permits relicensing
|
||||||
|
or conveying under this License, you may add to a covered work material governed
|
||||||
|
by the terms of that license document, provided that the further restriction
|
||||||
|
does not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you must place,
|
||||||
|
in the relevant source files, a statement of the additional terms that apply
|
||||||
|
to those files, or a notice indicating where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the form
|
||||||
|
of a separately written license, or stated as exceptions; the above requirements
|
||||||
|
apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly provided
|
||||||
|
under this License. Any attempt otherwise to propagate or modify it is void,
|
||||||
|
and will automatically terminate your rights under this License (including
|
||||||
|
any patent licenses granted under the third paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your license from
|
||||||
|
a particular copyright holder is reinstated (a) provisionally, unless and
|
||||||
|
until the copyright holder explicitly and finally terminates your license,
|
||||||
|
and (b) permanently, if the copyright holder fails to notify you of the violation
|
||||||
|
by some reasonable means prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is reinstated permanently
|
||||||
|
if the copyright holder notifies you of the violation by some reasonable means,
|
||||||
|
this is the first time you have received notice of violation of this License
|
||||||
|
(for any work) from that copyright holder, and you cure the violation prior
|
||||||
|
to 30 days after your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the licenses
|
||||||
|
of parties who have received copies or rights from you under this License.
|
||||||
|
If your rights have been terminated and not permanently reinstated, you do
|
||||||
|
not qualify to receive new licenses for the same material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or run a copy
|
||||||
|
of the Program. Ancillary propagation of a covered work occurring solely as
|
||||||
|
a consequence of using peer-to-peer transmission to receive a copy likewise
|
||||||
|
does not require acceptance. However, nothing other than this License grants
|
||||||
|
you permission to propagate or modify any covered work. These actions infringe
|
||||||
|
copyright if you do not accept this License. Therefore, by modifying or propagating
|
||||||
|
a covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically receives
|
||||||
|
a license from the original licensors, to run, modify and propagate that work,
|
||||||
|
subject to this License. You are not responsible for enforcing compliance
|
||||||
|
by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an organization,
|
||||||
|
or substantially all assets of one, or subdividing an organization, or merging
|
||||||
|
organizations. If propagation of a covered work results from an entity transaction,
|
||||||
|
each party to that transaction who receives a copy of the work also receives
|
||||||
|
whatever licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the Corresponding
|
||||||
|
Source of the work from the predecessor in interest, if the predecessor has
|
||||||
|
it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the rights
|
||||||
|
granted or affirmed under this License. For example, you may not impose a
|
||||||
|
license fee, royalty, or other charge for exercise of rights granted under
|
||||||
|
this License, and you may not initiate litigation (including a cross-claim
|
||||||
|
or counterclaim in a lawsuit) alleging that any patent claim is infringed
|
||||||
|
by making, using, selling, offering for sale, or importing the Program or
|
||||||
|
any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this License
|
||||||
|
of the Program or a work on which the Program is based. The work thus licensed
|
||||||
|
is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims owned or controlled
|
||||||
|
by the contributor, whether already acquired or hereafter acquired, that would
|
||||||
|
be infringed by some manner, permitted by this License, of making, using,
|
||||||
|
or selling its contributor version, but do not include claims that would be
|
||||||
|
infringed only as a consequence of further modification of the contributor
|
||||||
|
version. For purposes of this definition, "control" includes the right to
|
||||||
|
grant patent sublicenses in a manner consistent with the requirements of this
|
||||||
|
License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free patent
|
||||||
|
license under the contributor's essential patent claims, to make, use, sell,
|
||||||
|
offer for sale, import and otherwise run, modify and propagate the contents
|
||||||
|
of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express agreement
|
||||||
|
or commitment, however denominated, not to enforce a patent (such as an express
|
||||||
|
permission to practice a patent or covenant not to sue for patent infringement).
|
||||||
|
To "grant" such a patent license to a party means to make such an agreement
|
||||||
|
or commitment not to enforce a patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license, and the
|
||||||
|
Corresponding Source of the work is not available for anyone to copy, free
|
||||||
|
of charge and under the terms of this License, through a publicly available
|
||||||
|
network server or other readily accessible means, then you must either (1)
|
||||||
|
cause the Corresponding Source to be so available, or (2) arrange to deprive
|
||||||
|
yourself of the benefit of the patent license for this particular work, or
|
||||||
|
(3) arrange, in a manner consistent with the requirements of this License,
|
||||||
|
to extend the patent license to downstream recipients. "Knowingly relying"
|
||||||
|
means you have actual knowledge that, but for the patent license, your conveying
|
||||||
|
the covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that country
|
||||||
|
that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or arrangement,
|
||||||
|
you convey, or propagate by procuring conveyance of, a covered work, and grant
|
||||||
|
a patent license to some of the parties receiving the covered work authorizing
|
||||||
|
them to use, propagate, modify or convey a specific copy of the covered work,
|
||||||
|
then the patent license you grant is automatically extended to all recipients
|
||||||
|
of the covered work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within the scope
|
||||||
|
of its coverage, prohibits the exercise of, or is conditioned on the non-exercise
|
||||||
|
of one or more of the rights that are specifically granted under this License.
|
||||||
|
You may not convey a covered work if you are a party to an arrangement with
|
||||||
|
a third party that is in the business of distributing software, under which
|
||||||
|
you make payment to the third party based on the extent of your activity of
|
||||||
|
conveying the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory patent
|
||||||
|
license (a) in connection with copies of the covered work conveyed by you
|
||||||
|
(or copies made from those copies), or (b) primarily for and in connection
|
||||||
|
with specific products or compilations that contain the covered work, unless
|
||||||
|
you entered into that arrangement, or that patent license was granted, prior
|
||||||
|
to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting any implied
|
||||||
|
license or other defenses to infringement that may otherwise be available
|
||||||
|
to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or otherwise)
|
||||||
|
that contradict the conditions of this License, they do not excuse you from
|
||||||
|
the conditions of this License. If you cannot convey a covered work so as
|
||||||
|
to satisfy simultaneously your obligations under this License and any other
|
||||||
|
pertinent obligations, then as a consequence you may not convey it at all.
|
||||||
|
For example, if you agree to terms that obligate you to collect a royalty
|
||||||
|
for further conveying from those to whom you convey the Program, the only
|
||||||
|
way you could satisfy both those terms and this License would be to refrain
|
||||||
|
entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have permission to
|
||||||
|
link or combine any covered work with a work licensed under version 3 of the
|
||||||
|
GNU Affero General Public License into a single combined work, and to convey
|
||||||
|
the resulting work. The terms of this License will continue to apply to the
|
||||||
|
part which is the covered work, but the special requirements of the GNU Affero
|
||||||
|
General Public License, section 13, concerning interaction through a network
|
||||||
|
will apply to the combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of the
|
||||||
|
GNU General Public License from time to time. Such new versions will be similar
|
||||||
|
in spirit to the present version, but may differ in detail to address new
|
||||||
|
problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program specifies
|
||||||
|
that a certain numbered version of the GNU General Public License "or any
|
||||||
|
later version" applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that numbered version or of any later version published
|
||||||
|
by the Free Software Foundation. If the Program does not specify a version
|
||||||
|
number of the GNU General Public License, you may choose any version ever
|
||||||
|
published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future versions of
|
||||||
|
the GNU General Public License can be used, that proxy's public statement
|
||||||
|
of acceptance of a version permanently authorizes you to choose that version
|
||||||
|
for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different permissions. However,
|
||||||
|
no additional obligations are imposed on any author or copyright holder as
|
||||||
|
a result of your choosing to follow a later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE
|
||||||
|
LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||||
|
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM
|
||||||
|
PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
|
||||||
|
CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
|
||||||
|
ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM
|
||||||
|
AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
|
||||||
|
INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO
|
||||||
|
USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
|
||||||
|
INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE
|
||||||
|
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
|
||||||
|
PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided above cannot
|
||||||
|
be given local legal effect according to their terms, reviewing courts shall
|
||||||
|
apply local law that most closely approximates an absolute waiver of all civil
|
||||||
|
liability in connection with the Program, unless a warranty or assumption
|
||||||
|
of liability accompanies a copy of the Program in return for a fee. END OF
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest possible
|
||||||
|
use to the public, the best way to achieve this is to make it free software
|
||||||
|
which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest to attach
|
||||||
|
them to the start of each source file to most effectively state the exclusion
|
||||||
|
of warranty; and each file should have at least the "copyright" line and a
|
||||||
|
pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short notice like
|
||||||
|
this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
|
||||||
|
This is free software, and you are welcome to redistribute it under certain
|
||||||
|
conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands might
|
||||||
|
be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary. For
|
||||||
|
more information on this, and how to apply and follow the GNU GPL, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General Public
|
||||||
|
License instead of this License. But first, please read <https://www.gnu.org/
|
||||||
|
licenses /why-not-lgpl.html>.
|
122
README.md
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
# EndOfYear
|
||||||
|
|
||||||
|
EndOfYear 点燃个人博客的年度辉煌!
|
||||||
|
|
||||||
|
![EndOfYear](static/endofyear.jpg)
|
||||||
|
|
||||||
|
## 流程
|
||||||
|
|
||||||
|
EndOfYear 通过 RSS 获取博客文章数据,对文章数据进行统计、分析和整理,最终输出为 HTML,客观地反映了博客一年的写作情况。
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
actor User
|
||||||
|
participant Flask
|
||||||
|
participant Config
|
||||||
|
participant Generator
|
||||||
|
participant Scraper
|
||||||
|
participant Analyzer
|
||||||
|
|
||||||
|
User ->> Flask: Access service
|
||||||
|
Flask ->> Config: Check cache
|
||||||
|
activate Config
|
||||||
|
alt Cache exists
|
||||||
|
Config -->> Flask: Return cached data
|
||||||
|
else Cache does not exist
|
||||||
|
Config ->> Generator: Run data generator
|
||||||
|
activate Generator
|
||||||
|
Generator ->> Scraper: Run data scraping
|
||||||
|
activate Scraper
|
||||||
|
Scraper -->> Generator: Return scraped data
|
||||||
|
deactivate Scraper
|
||||||
|
Generator ->> Analyzer: Run data analysis
|
||||||
|
activate Analyzer
|
||||||
|
Analyzer -->> Generator: Return analyzed data
|
||||||
|
deactivate Analyzer
|
||||||
|
Generator -->> Config: Return organized data
|
||||||
|
deactivate Generator
|
||||||
|
Config -->> Flask: Return data
|
||||||
|
end
|
||||||
|
Flask -->> User: Return HTML page
|
||||||
|
deactivate Config
|
||||||
|
```
|
||||||
|
|
||||||
|
1. 用户访问 Flask 服务。
|
||||||
|
2. Flask 检查缓存是否存在。
|
||||||
|
- 如果缓存存在,Flask直接返回缓存数据。
|
||||||
|
- 如果缓存不存在,继续下一步。
|
||||||
|
3. Config 模块运行数据生成器(Generator)。
|
||||||
|
4. Generator 模块运行数据抓取器(Scraper)来获取RSS数据。
|
||||||
|
5. Scraper 将抓取的数据返回给 Generator。
|
||||||
|
6. Generator 运行数据分析器(Analyzer)对数据进行分析。
|
||||||
|
7. Analyzer 将分析后的数据返回给 Generator。
|
||||||
|
8. Generator 整理结构化数据后将其返回给 Flask,Config 模块。
|
||||||
|
9. Flask 使用整理后的数据渲染 HTML 页面。
|
||||||
|
10. Flask 返回渲染后的 HTML 页面给用户。
|
||||||
|
|
||||||
|
## 用法
|
||||||
|
|
||||||
|
### Github
|
||||||
|
|
||||||
|
1. Fork 项目到个人仓库
|
||||||
|
2. 手动配置仓库的 Workflow permissions 设置为 **Read and write permissions**,否则无法写入 html 分支。
|
||||||
|
1. 导航到 **Settings**(设置)选项卡。
|
||||||
|
2. 在左侧导航栏中,点击 **Actions**(操作)。
|
||||||
|
3. 在 **General**(常规)页面下滑,找到 **Workflow permissions**(工作流权限)。
|
||||||
|
4. 在 **Workflow permissions** 中,选择 **Read and write permissions**(读写权限)。
|
||||||
|
5. 最后点击 **Save**(保存)。
|
||||||
|
3. 在仓库首页打开目录下的 `config.ini` 配置文件,点击右上角工具栏的 **🖋️(钢笔)** 图标,在线编辑文件。
|
||||||
|
- `web`:配置为 `false`。
|
||||||
|
- `rss`:配置为 RSS 地址。
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[default]
|
||||||
|
web = false
|
||||||
|
|
||||||
|
[blog]
|
||||||
|
rss = https://blog.7wate.com/rss.xml
|
||||||
|
data =
|
||||||
|
```
|
||||||
|
|
||||||
|
4. 点击右上角的 **Commit changes** 提交到 `main` 分支,会自动运行 Action。
|
||||||
|
5. 等待 Action 运行成功,将会部署静态网站文件至 `html` 分支。
|
||||||
|
|
||||||
|
6. 开启仓库的 Pages 功能,默认为根目录。
|
||||||
|
7. 访问个人网址,就可以看到啦~
|
||||||
|
|
||||||
|
### Docker
|
||||||
|
|
||||||
|
1. 拉取最新镜像
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker pull sevewate/endofyear:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 指定 `rss_url` 环境变量,运行 Docker。请将 `https://blog.7wate.com/rss.xml` 替换为自己的 RSS 地址。
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker run -p 7777:7777 --env rss=https://blog.7wate.com/rss.xml sevewate/endofyear:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 访问网址 `localhost:7777`
|
||||||
|
|
||||||
|
## 路线图
|
||||||
|
|
||||||
|
EndOfYear 目前处于初始阶段,如果您有兴趣,可以为其做出贡献。计划路线如下:
|
||||||
|
|
||||||
|
### V1
|
||||||
|
|
||||||
|
- [ ] 对博客系统的数据源进行全面、规模性的测试。
|
||||||
|
- [ ] 进一步细化数据分析维度和数据颗粒度,精准描绘用户画像。
|
||||||
|
- [ ] 渲染数据的规范,约束主题开发,提高主题的兼容性。
|
||||||
|
|
||||||
|
### V2
|
||||||
|
|
||||||
|
- [ ] 丰富和完善主题。
|
||||||
|
- [ ] 实现轻量化的运行部署,一键运行。
|
||||||
|
- [ ] 探索以插件的方式附加到博客系统的方法。
|
||||||
|
|
||||||
|
|
||||||
|
## 协议
|
||||||
|
|
||||||
|
EndOfYear 采用 GPL 3.0 协议。
|
6
config.ini
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[default]
|
||||||
|
web = true
|
||||||
|
|
||||||
|
[blog]
|
||||||
|
rss =
|
||||||
|
data =
|
767
data/stop_words.txt
Normal file
@ -0,0 +1,767 @@
|
|||||||
|
———
|
||||||
|
》),
|
||||||
|
)÷(1-
|
||||||
|
”,
|
||||||
|
)、
|
||||||
|
=(
|
||||||
|
:
|
||||||
|
→
|
||||||
|
℃
|
||||||
|
&
|
||||||
|
*
|
||||||
|
一一
|
||||||
|
~~~~
|
||||||
|
’
|
||||||
|
.
|
||||||
|
『
|
||||||
|
.一
|
||||||
|
./
|
||||||
|
--
|
||||||
|
』
|
||||||
|
=″
|
||||||
|
【
|
||||||
|
[*]
|
||||||
|
}>
|
||||||
|
[⑤]]
|
||||||
|
[①D]
|
||||||
|
c]
|
||||||
|
ng昉
|
||||||
|
*
|
||||||
|
//
|
||||||
|
[
|
||||||
|
]
|
||||||
|
[②e]
|
||||||
|
[②g]
|
||||||
|
={
|
||||||
|
}
|
||||||
|
,也
|
||||||
|
‘
|
||||||
|
A
|
||||||
|
[①⑥]
|
||||||
|
[②B]
|
||||||
|
[①a]
|
||||||
|
[④a]
|
||||||
|
[①③]
|
||||||
|
[③h]
|
||||||
|
③]
|
||||||
|
1.
|
||||||
|
--
|
||||||
|
[②b]
|
||||||
|
’‘
|
||||||
|
×××
|
||||||
|
[①⑧]
|
||||||
|
0:2
|
||||||
|
=[
|
||||||
|
[⑤b]
|
||||||
|
[②c]
|
||||||
|
[④b]
|
||||||
|
[②③]
|
||||||
|
[③a]
|
||||||
|
[④c]
|
||||||
|
[①⑤]
|
||||||
|
[①⑦]
|
||||||
|
[①g]
|
||||||
|
∈[
|
||||||
|
[①⑨]
|
||||||
|
[①④]
|
||||||
|
[①c]
|
||||||
|
[②f]
|
||||||
|
[②⑧]
|
||||||
|
[②①]
|
||||||
|
[①C]
|
||||||
|
[③c]
|
||||||
|
[③g]
|
||||||
|
[②⑤]
|
||||||
|
[②②]
|
||||||
|
一.
|
||||||
|
[①h]
|
||||||
|
.数
|
||||||
|
[]
|
||||||
|
[①B]
|
||||||
|
数/
|
||||||
|
[①i]
|
||||||
|
[③e]
|
||||||
|
[①①]
|
||||||
|
[④d]
|
||||||
|
[④e]
|
||||||
|
[③b]
|
||||||
|
[⑤a]
|
||||||
|
[①A]
|
||||||
|
[②⑧]
|
||||||
|
[②⑦]
|
||||||
|
[①d]
|
||||||
|
[②j]
|
||||||
|
〕〔
|
||||||
|
][
|
||||||
|
://
|
||||||
|
′∈
|
||||||
|
[②④
|
||||||
|
[⑤e]
|
||||||
|
12%
|
||||||
|
b]
|
||||||
|
...
|
||||||
|
...................
|
||||||
|
…………………………………………………③
|
||||||
|
ZXFITL
|
||||||
|
[③F]
|
||||||
|
」
|
||||||
|
[①o]
|
||||||
|
]∧′=[
|
||||||
|
∪φ∈
|
||||||
|
′|
|
||||||
|
{-
|
||||||
|
②c
|
||||||
|
}
|
||||||
|
[③①]
|
||||||
|
R.L.
|
||||||
|
[①E]
|
||||||
|
Ψ
|
||||||
|
-[*]-
|
||||||
|
↑
|
||||||
|
.日
|
||||||
|
[②d]
|
||||||
|
[②
|
||||||
|
[②⑦]
|
||||||
|
[②②]
|
||||||
|
[③e]
|
||||||
|
[①i]
|
||||||
|
[①B]
|
||||||
|
[①h]
|
||||||
|
[①d]
|
||||||
|
[①g]
|
||||||
|
[①②]
|
||||||
|
[②a]
|
||||||
|
f]
|
||||||
|
[⑩]
|
||||||
|
a]
|
||||||
|
[①e]
|
||||||
|
[②h]
|
||||||
|
[②⑥]
|
||||||
|
[③d]
|
||||||
|
[②⑩]
|
||||||
|
e]
|
||||||
|
〉
|
||||||
|
】
|
||||||
|
元/吨
|
||||||
|
[②⑩]
|
||||||
|
2.3%
|
||||||
|
5:0
|
||||||
|
[①]
|
||||||
|
::
|
||||||
|
[②]
|
||||||
|
[③]
|
||||||
|
[④]
|
||||||
|
[⑤]
|
||||||
|
[⑥]
|
||||||
|
[⑦]
|
||||||
|
[⑧]
|
||||||
|
[⑨]
|
||||||
|
……
|
||||||
|
——
|
||||||
|
?
|
||||||
|
、
|
||||||
|
。
|
||||||
|
“
|
||||||
|
”
|
||||||
|
《
|
||||||
|
》
|
||||||
|
!
|
||||||
|
,
|
||||||
|
:
|
||||||
|
;
|
||||||
|
?
|
||||||
|
.
|
||||||
|
,
|
||||||
|
.
|
||||||
|
'
|
||||||
|
?
|
||||||
|
·
|
||||||
|
———
|
||||||
|
──
|
||||||
|
?
|
||||||
|
—
|
||||||
|
<
|
||||||
|
>
|
||||||
|
(
|
||||||
|
)
|
||||||
|
〔
|
||||||
|
〕
|
||||||
|
[
|
||||||
|
]
|
||||||
|
(
|
||||||
|
)
|
||||||
|
-
|
||||||
|
+
|
||||||
|
~
|
||||||
|
×
|
||||||
|
/
|
||||||
|
/
|
||||||
|
①
|
||||||
|
②
|
||||||
|
③
|
||||||
|
④
|
||||||
|
⑤
|
||||||
|
⑥
|
||||||
|
⑦
|
||||||
|
⑧
|
||||||
|
⑨
|
||||||
|
⑩
|
||||||
|
Ⅲ
|
||||||
|
В
|
||||||
|
"
|
||||||
|
;
|
||||||
|
#
|
||||||
|
@
|
||||||
|
γ
|
||||||
|
μ
|
||||||
|
φ
|
||||||
|
φ.
|
||||||
|
×
|
||||||
|
Δ
|
||||||
|
■
|
||||||
|
▲
|
||||||
|
sub
|
||||||
|
exp
|
||||||
|
sup
|
||||||
|
sub
|
||||||
|
Lex
|
||||||
|
#
|
||||||
|
%
|
||||||
|
&
|
||||||
|
'
|
||||||
|
+
|
||||||
|
+ξ
|
||||||
|
++
|
||||||
|
-
|
||||||
|
-β
|
||||||
|
<
|
||||||
|
<±
|
||||||
|
<Δ
|
||||||
|
<λ
|
||||||
|
<φ
|
||||||
|
<<
|
||||||
|
=
|
||||||
|
=
|
||||||
|
=☆
|
||||||
|
=-
|
||||||
|
>
|
||||||
|
>λ
|
||||||
|
_
|
||||||
|
~±
|
||||||
|
~+
|
||||||
|
[⑤f]
|
||||||
|
[⑤d]
|
||||||
|
[②i]
|
||||||
|
≈
|
||||||
|
[②G]
|
||||||
|
[①f]
|
||||||
|
LI
|
||||||
|
㈧
|
||||||
|
[-
|
||||||
|
......
|
||||||
|
〉
|
||||||
|
[③⑩]
|
||||||
|
第二
|
||||||
|
一番
|
||||||
|
一直
|
||||||
|
一个
|
||||||
|
一些
|
||||||
|
许多
|
||||||
|
种
|
||||||
|
有的是
|
||||||
|
也就是说
|
||||||
|
末##末
|
||||||
|
啊
|
||||||
|
阿
|
||||||
|
哎
|
||||||
|
哎呀
|
||||||
|
哎哟
|
||||||
|
唉
|
||||||
|
俺
|
||||||
|
俺们
|
||||||
|
按
|
||||||
|
按照
|
||||||
|
吧
|
||||||
|
吧哒
|
||||||
|
把
|
||||||
|
罢了
|
||||||
|
被
|
||||||
|
本
|
||||||
|
本着
|
||||||
|
比
|
||||||
|
比方
|
||||||
|
比如
|
||||||
|
鄙人
|
||||||
|
彼
|
||||||
|
彼此
|
||||||
|
边
|
||||||
|
别
|
||||||
|
别的
|
||||||
|
别说
|
||||||
|
并
|
||||||
|
并且
|
||||||
|
不比
|
||||||
|
不成
|
||||||
|
不单
|
||||||
|
不但
|
||||||
|
不独
|
||||||
|
不管
|
||||||
|
不光
|
||||||
|
不过
|
||||||
|
不仅
|
||||||
|
不拘
|
||||||
|
不论
|
||||||
|
不怕
|
||||||
|
不然
|
||||||
|
不如
|
||||||
|
不特
|
||||||
|
不惟
|
||||||
|
不问
|
||||||
|
不只
|
||||||
|
朝
|
||||||
|
朝着
|
||||||
|
趁
|
||||||
|
趁着
|
||||||
|
乘
|
||||||
|
冲
|
||||||
|
除
|
||||||
|
除此之外
|
||||||
|
除非
|
||||||
|
除了
|
||||||
|
此
|
||||||
|
此间
|
||||||
|
此外
|
||||||
|
从
|
||||||
|
从而
|
||||||
|
打
|
||||||
|
待
|
||||||
|
但
|
||||||
|
但是
|
||||||
|
当
|
||||||
|
当着
|
||||||
|
到
|
||||||
|
得
|
||||||
|
的
|
||||||
|
的话
|
||||||
|
等
|
||||||
|
等等
|
||||||
|
地
|
||||||
|
第
|
||||||
|
叮咚
|
||||||
|
对
|
||||||
|
对于
|
||||||
|
多
|
||||||
|
多少
|
||||||
|
而
|
||||||
|
而况
|
||||||
|
而且
|
||||||
|
而是
|
||||||
|
而外
|
||||||
|
而言
|
||||||
|
而已
|
||||||
|
尔后
|
||||||
|
反过来
|
||||||
|
反过来说
|
||||||
|
反之
|
||||||
|
非但
|
||||||
|
非徒
|
||||||
|
否则
|
||||||
|
嘎
|
||||||
|
嘎登
|
||||||
|
该
|
||||||
|
赶
|
||||||
|
个
|
||||||
|
各
|
||||||
|
各个
|
||||||
|
各位
|
||||||
|
各种
|
||||||
|
各自
|
||||||
|
给
|
||||||
|
根据
|
||||||
|
跟
|
||||||
|
故
|
||||||
|
故此
|
||||||
|
固然
|
||||||
|
关于
|
||||||
|
管
|
||||||
|
归
|
||||||
|
果然
|
||||||
|
果真
|
||||||
|
过
|
||||||
|
哈
|
||||||
|
哈哈
|
||||||
|
呵
|
||||||
|
和
|
||||||
|
何
|
||||||
|
何处
|
||||||
|
何况
|
||||||
|
何时
|
||||||
|
嘿
|
||||||
|
哼
|
||||||
|
哼唷
|
||||||
|
呼哧
|
||||||
|
乎
|
||||||
|
哗
|
||||||
|
还是
|
||||||
|
还有
|
||||||
|
换句话说
|
||||||
|
换言之
|
||||||
|
或
|
||||||
|
或是
|
||||||
|
或者
|
||||||
|
极了
|
||||||
|
及
|
||||||
|
及其
|
||||||
|
及至
|
||||||
|
即
|
||||||
|
即便
|
||||||
|
即或
|
||||||
|
即令
|
||||||
|
即若
|
||||||
|
即使
|
||||||
|
几
|
||||||
|
几时
|
||||||
|
己
|
||||||
|
既
|
||||||
|
既然
|
||||||
|
既是
|
||||||
|
继而
|
||||||
|
加之
|
||||||
|
假如
|
||||||
|
假若
|
||||||
|
假使
|
||||||
|
鉴于
|
||||||
|
将
|
||||||
|
较
|
||||||
|
较之
|
||||||
|
叫
|
||||||
|
接着
|
||||||
|
结果
|
||||||
|
借
|
||||||
|
紧接着
|
||||||
|
进而
|
||||||
|
尽
|
||||||
|
尽管
|
||||||
|
经
|
||||||
|
经过
|
||||||
|
就
|
||||||
|
就是
|
||||||
|
就是说
|
||||||
|
据
|
||||||
|
具体地说
|
||||||
|
具体说来
|
||||||
|
开始
|
||||||
|
开外
|
||||||
|
靠
|
||||||
|
咳
|
||||||
|
可
|
||||||
|
可见
|
||||||
|
可是
|
||||||
|
可以
|
||||||
|
况且
|
||||||
|
啦
|
||||||
|
来
|
||||||
|
来着
|
||||||
|
离
|
||||||
|
例如
|
||||||
|
哩
|
||||||
|
连
|
||||||
|
连同
|
||||||
|
两者
|
||||||
|
了
|
||||||
|
临
|
||||||
|
另
|
||||||
|
另外
|
||||||
|
另一方面
|
||||||
|
论
|
||||||
|
嘛
|
||||||
|
吗
|
||||||
|
慢说
|
||||||
|
漫说
|
||||||
|
冒
|
||||||
|
么
|
||||||
|
每
|
||||||
|
每当
|
||||||
|
们
|
||||||
|
莫若
|
||||||
|
某
|
||||||
|
某个
|
||||||
|
某些
|
||||||
|
拿
|
||||||
|
哪
|
||||||
|
哪边
|
||||||
|
哪儿
|
||||||
|
哪个
|
||||||
|
哪里
|
||||||
|
哪年
|
||||||
|
哪怕
|
||||||
|
哪天
|
||||||
|
哪些
|
||||||
|
哪样
|
||||||
|
那
|
||||||
|
那边
|
||||||
|
那儿
|
||||||
|
那个
|
||||||
|
那会儿
|
||||||
|
那里
|
||||||
|
那么
|
||||||
|
那么些
|
||||||
|
那么样
|
||||||
|
那时
|
||||||
|
那些
|
||||||
|
那样
|
||||||
|
乃
|
||||||
|
乃至
|
||||||
|
呢
|
||||||
|
能
|
||||||
|
你
|
||||||
|
你们
|
||||||
|
您
|
||||||
|
宁
|
||||||
|
宁可
|
||||||
|
宁肯
|
||||||
|
宁愿
|
||||||
|
哦
|
||||||
|
呕
|
||||||
|
啪达
|
||||||
|
旁人
|
||||||
|
呸
|
||||||
|
凭
|
||||||
|
凭借
|
||||||
|
其
|
||||||
|
其次
|
||||||
|
其二
|
||||||
|
其他
|
||||||
|
其它
|
||||||
|
其一
|
||||||
|
其余
|
||||||
|
其中
|
||||||
|
起
|
||||||
|
起见
|
||||||
|
起见
|
||||||
|
岂但
|
||||||
|
恰恰相反
|
||||||
|
前后
|
||||||
|
前者
|
||||||
|
且
|
||||||
|
然而
|
||||||
|
然后
|
||||||
|
然则
|
||||||
|
让
|
||||||
|
人家
|
||||||
|
任
|
||||||
|
任何
|
||||||
|
任凭
|
||||||
|
如
|
||||||
|
如此
|
||||||
|
如果
|
||||||
|
如何
|
||||||
|
如其
|
||||||
|
如若
|
||||||
|
如上所述
|
||||||
|
若
|
||||||
|
若非
|
||||||
|
若是
|
||||||
|
啥
|
||||||
|
上下
|
||||||
|
尚且
|
||||||
|
设若
|
||||||
|
设使
|
||||||
|
甚而
|
||||||
|
甚么
|
||||||
|
甚至
|
||||||
|
省得
|
||||||
|
时候
|
||||||
|
什么
|
||||||
|
什么样
|
||||||
|
使得
|
||||||
|
是
|
||||||
|
是的
|
||||||
|
首先
|
||||||
|
谁
|
||||||
|
谁知
|
||||||
|
顺
|
||||||
|
顺着
|
||||||
|
似的
|
||||||
|
虽
|
||||||
|
虽然
|
||||||
|
虽说
|
||||||
|
虽则
|
||||||
|
随
|
||||||
|
随着
|
||||||
|
所
|
||||||
|
所以
|
||||||
|
他
|
||||||
|
他们
|
||||||
|
他人
|
||||||
|
它
|
||||||
|
它们
|
||||||
|
她
|
||||||
|
她们
|
||||||
|
倘
|
||||||
|
倘或
|
||||||
|
倘然
|
||||||
|
倘若
|
||||||
|
倘使
|
||||||
|
腾
|
||||||
|
替
|
||||||
|
通过
|
||||||
|
同
|
||||||
|
同时
|
||||||
|
哇
|
||||||
|
万一
|
||||||
|
往
|
||||||
|
望
|
||||||
|
为
|
||||||
|
为何
|
||||||
|
为了
|
||||||
|
为什么
|
||||||
|
为着
|
||||||
|
喂
|
||||||
|
嗡嗡
|
||||||
|
我
|
||||||
|
我们
|
||||||
|
呜
|
||||||
|
呜呼
|
||||||
|
乌乎
|
||||||
|
无论
|
||||||
|
无宁
|
||||||
|
毋宁
|
||||||
|
嘻
|
||||||
|
吓
|
||||||
|
相对而言
|
||||||
|
像
|
||||||
|
向
|
||||||
|
向着
|
||||||
|
嘘
|
||||||
|
呀
|
||||||
|
焉
|
||||||
|
沿
|
||||||
|
沿着
|
||||||
|
要
|
||||||
|
要不
|
||||||
|
要不然
|
||||||
|
要不是
|
||||||
|
要么
|
||||||
|
要是
|
||||||
|
也
|
||||||
|
也罢
|
||||||
|
也好
|
||||||
|
一
|
||||||
|
一般
|
||||||
|
一旦
|
||||||
|
一方面
|
||||||
|
一来
|
||||||
|
一切
|
||||||
|
一样
|
||||||
|
一则
|
||||||
|
依
|
||||||
|
依照
|
||||||
|
矣
|
||||||
|
以
|
||||||
|
以便
|
||||||
|
以及
|
||||||
|
以免
|
||||||
|
以至
|
||||||
|
以至于
|
||||||
|
以致
|
||||||
|
抑或
|
||||||
|
因
|
||||||
|
因此
|
||||||
|
因而
|
||||||
|
因为
|
||||||
|
哟
|
||||||
|
用
|
||||||
|
由
|
||||||
|
由此可见
|
||||||
|
由于
|
||||||
|
有
|
||||||
|
有的
|
||||||
|
有关
|
||||||
|
有些
|
||||||
|
又
|
||||||
|
于
|
||||||
|
于是
|
||||||
|
于是乎
|
||||||
|
与
|
||||||
|
与此同时
|
||||||
|
与否
|
||||||
|
与其
|
||||||
|
越是
|
||||||
|
云云
|
||||||
|
哉
|
||||||
|
再说
|
||||||
|
再者
|
||||||
|
在
|
||||||
|
在下
|
||||||
|
咱
|
||||||
|
咱们
|
||||||
|
则
|
||||||
|
怎
|
||||||
|
怎么
|
||||||
|
怎么办
|
||||||
|
怎么样
|
||||||
|
怎样
|
||||||
|
咋
|
||||||
|
照
|
||||||
|
照着
|
||||||
|
者
|
||||||
|
这
|
||||||
|
这边
|
||||||
|
这儿
|
||||||
|
这个
|
||||||
|
这会儿
|
||||||
|
这就是说
|
||||||
|
这里
|
||||||
|
这么
|
||||||
|
这么点儿
|
||||||
|
这么些
|
||||||
|
这么样
|
||||||
|
这时
|
||||||
|
这些
|
||||||
|
这样
|
||||||
|
正如
|
||||||
|
吱
|
||||||
|
之
|
||||||
|
之类
|
||||||
|
之所以
|
||||||
|
之一
|
||||||
|
只是
|
||||||
|
只限
|
||||||
|
只要
|
||||||
|
只有
|
||||||
|
至
|
||||||
|
至于
|
||||||
|
诸位
|
||||||
|
着
|
||||||
|
着呢
|
||||||
|
自
|
||||||
|
自从
|
||||||
|
自个儿
|
||||||
|
自各儿
|
||||||
|
自己
|
||||||
|
自家
|
||||||
|
自身
|
||||||
|
综上所述
|
||||||
|
总的来看
|
||||||
|
总的来说
|
||||||
|
总的说来
|
||||||
|
总而言之
|
||||||
|
总之
|
||||||
|
纵
|
||||||
|
纵令
|
||||||
|
纵然
|
||||||
|
纵使
|
||||||
|
遵照
|
||||||
|
作为
|
||||||
|
兮
|
||||||
|
呃
|
||||||
|
呗
|
||||||
|
咚
|
||||||
|
咦
|
||||||
|
喏
|
||||||
|
啐
|
||||||
|
喔唷
|
||||||
|
嗬
|
||||||
|
嗯
|
||||||
|
嗳
|
247
data/tech_terms.txt
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
Python
|
||||||
|
Java
|
||||||
|
JavaScript
|
||||||
|
C
|
||||||
|
C++
|
||||||
|
C#
|
||||||
|
PHP
|
||||||
|
Ruby
|
||||||
|
Go
|
||||||
|
Swift
|
||||||
|
Kotlin
|
||||||
|
Rust
|
||||||
|
TypeScript
|
||||||
|
HTML
|
||||||
|
CSS
|
||||||
|
SQL
|
||||||
|
NoSQL
|
||||||
|
MongoDB
|
||||||
|
PostgreSQL
|
||||||
|
SQLite
|
||||||
|
Redis
|
||||||
|
Elasticsearch
|
||||||
|
Docker
|
||||||
|
Kubernetes
|
||||||
|
Microservices
|
||||||
|
Angular
|
||||||
|
React
|
||||||
|
Vue
|
||||||
|
Node.js
|
||||||
|
Express
|
||||||
|
Django
|
||||||
|
Flask
|
||||||
|
Spring Boot
|
||||||
|
.NET
|
||||||
|
TensorFlow
|
||||||
|
PyTorch
|
||||||
|
Pandas
|
||||||
|
NumPy
|
||||||
|
Scikit-learn
|
||||||
|
Matplotlib
|
||||||
|
Seaborn
|
||||||
|
Bokeh
|
||||||
|
Jupyter
|
||||||
|
Data Science
|
||||||
|
Machine Learning
|
||||||
|
Deep Learning
|
||||||
|
Artificial Intelligence
|
||||||
|
Natural Language Processing
|
||||||
|
Computer Vision
|
||||||
|
Reinforcement Learning
|
||||||
|
Neural Network
|
||||||
|
Convolutional Neural Network
|
||||||
|
Recurrent Neural Network
|
||||||
|
GANs
|
||||||
|
Blockchain
|
||||||
|
Bitcoin
|
||||||
|
Ethereum
|
||||||
|
Smart Contract
|
||||||
|
Cloud Computing
|
||||||
|
AWS
|
||||||
|
Azure
|
||||||
|
GCP
|
||||||
|
Serverless
|
||||||
|
DevOps
|
||||||
|
Git
|
||||||
|
GitHub
|
||||||
|
Bitbucket
|
||||||
|
Agile
|
||||||
|
Scrum
|
||||||
|
Kanban
|
||||||
|
CI/CD
|
||||||
|
JUnit
|
||||||
|
Selenium
|
||||||
|
REST
|
||||||
|
GraphQL
|
||||||
|
JSON
|
||||||
|
XML
|
||||||
|
YAML
|
||||||
|
API
|
||||||
|
UI
|
||||||
|
UX
|
||||||
|
VR
|
||||||
|
AR
|
||||||
|
IoT
|
||||||
|
Raspberry Pi
|
||||||
|
Arduino
|
||||||
|
Linux
|
||||||
|
Ubuntu
|
||||||
|
CentOS
|
||||||
|
Fedora
|
||||||
|
Debian
|
||||||
|
Windows
|
||||||
|
macOS
|
||||||
|
Android
|
||||||
|
iOS
|
||||||
|
Firmware
|
||||||
|
Cybersecurity
|
||||||
|
Encryption
|
||||||
|
Firewall
|
||||||
|
VPN
|
||||||
|
DDoS
|
||||||
|
Malware
|
||||||
|
Ransomware
|
||||||
|
Phishing
|
||||||
|
Two-factor Authentication
|
||||||
|
Biometrics
|
||||||
|
Virtual Machine
|
||||||
|
Container
|
||||||
|
Orchestration
|
||||||
|
Big Data
|
||||||
|
Hadoop
|
||||||
|
Spark
|
||||||
|
Kafka
|
||||||
|
Flink
|
||||||
|
ETL
|
||||||
|
Data Warehouse
|
||||||
|
Business Intelligence
|
||||||
|
Data Mining
|
||||||
|
Web Scraping
|
||||||
|
Web Development
|
||||||
|
Frontend
|
||||||
|
Backend
|
||||||
|
Full Stack
|
||||||
|
Software Engineering
|
||||||
|
Database
|
||||||
|
Schema
|
||||||
|
Query
|
||||||
|
Indexing
|
||||||
|
Normalization
|
||||||
|
Denormalization
|
||||||
|
Object-Oriented Programming
|
||||||
|
Functional Programming
|
||||||
|
Procedural Programming
|
||||||
|
Scripting
|
||||||
|
Compiler
|
||||||
|
Interpreter
|
||||||
|
IDE
|
||||||
|
Debugging
|
||||||
|
Refactoring
|
||||||
|
Version Control
|
||||||
|
Concurrency
|
||||||
|
Multithreading
|
||||||
|
Synchronization
|
||||||
|
Deadlock
|
||||||
|
Memory Management
|
||||||
|
Garbage Collection
|
||||||
|
Exception Handling
|
||||||
|
PaaS
|
||||||
|
IaaS
|
||||||
|
SaaS
|
||||||
|
Hashing
|
||||||
|
Cryptography
|
||||||
|
Algorithm
|
||||||
|
Data Structure
|
||||||
|
Stack
|
||||||
|
Queue
|
||||||
|
Tree
|
||||||
|
Graph
|
||||||
|
Linked List
|
||||||
|
Array
|
||||||
|
Matrix
|
||||||
|
Sorting
|
||||||
|
Searching
|
||||||
|
BFS
|
||||||
|
DFS
|
||||||
|
Dynamic Programming
|
||||||
|
Greedy Algorithm
|
||||||
|
Divide and Conquer
|
||||||
|
Backtracking
|
||||||
|
Recursion
|
||||||
|
MapReduce
|
||||||
|
Object-Relational Mapping
|
||||||
|
Virtual Reality
|
||||||
|
Augmented Reality
|
||||||
|
Mixed Reality
|
||||||
|
Cyber-Physical System
|
||||||
|
Edge Computing
|
||||||
|
Fog Computing
|
||||||
|
Fifth Generation
|
||||||
|
Quantum Computing
|
||||||
|
Server
|
||||||
|
Client
|
||||||
|
Peer-to-Peer
|
||||||
|
Blockchain
|
||||||
|
Tangle
|
||||||
|
Distributed Ledger
|
||||||
|
Smart Grid
|
||||||
|
Autonomous Vehicle
|
||||||
|
Drone
|
||||||
|
3D Printing
|
||||||
|
Cryptocurrency
|
||||||
|
Token
|
||||||
|
Initial Coin Offering
|
||||||
|
Public Key
|
||||||
|
Private Key
|
||||||
|
Digital Signature
|
||||||
|
Zero-Knowledge Proof
|
||||||
|
Merkle Tree
|
||||||
|
Side Chain
|
||||||
|
Hard Fork
|
||||||
|
Soft Fork
|
||||||
|
Data Lake
|
||||||
|
Data Mart
|
||||||
|
OLAP
|
||||||
|
OLTP
|
||||||
|
CAP Theorem
|
||||||
|
ACID
|
||||||
|
BASE
|
||||||
|
Event-Driven
|
||||||
|
Microfrontend
|
||||||
|
Service Mesh
|
||||||
|
Progressive Web App
|
||||||
|
WebAssembly
|
||||||
|
GraphQL
|
||||||
|
gRPC
|
||||||
|
Thrift
|
||||||
|
Protocol Buffers
|
||||||
|
WebRTC
|
||||||
|
Socket.IO
|
||||||
|
OAuth
|
||||||
|
OpenID
|
||||||
|
LDAP
|
||||||
|
RBAC
|
||||||
|
XSS
|
||||||
|
CSRF
|
||||||
|
SQL Injection
|
||||||
|
Buffer Overflow
|
||||||
|
Shellshock
|
||||||
|
Heartbleed
|
||||||
|
Spectre
|
||||||
|
Meltdown
|
||||||
|
Row Hammer
|
||||||
|
BlueKeep
|
||||||
|
Zero Day
|
||||||
|
White Hat
|
||||||
|
Black Hat
|
||||||
|
Gray Hat
|
||||||
|
Rainbow Table
|
||||||
|
Brute Force
|
||||||
|
Dictionary Attack
|
||||||
|
Man in the Middle
|
||||||
|
Replay Attack
|
||||||
|
Denial of Service
|
||||||
|
SYN Flood
|
||||||
|
Smurf Attack
|
||||||
|
IP Spoofing
|
||||||
|
Phreaking
|
38
main.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
from flask import Flask, render_template, redirect, url_for
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
from src.config import Config
|
||||||
|
from src.generator import build_data
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
logger.add("endofyear.log")
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def home():
|
||||||
|
# 默认主题 painting
|
||||||
|
return redirect(url_for('painting'))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/painting')
|
||||||
|
def painting():
|
||||||
|
if Config("config.ini").web_status:
|
||||||
|
# web 服务
|
||||||
|
# 如果数据存在,直接返回
|
||||||
|
if blog_data := Config("config.ini").blog_data:
|
||||||
|
return render_template('painting.html', data=blog_data, web_status=1)
|
||||||
|
|
||||||
|
# 如果数据不存在,需要生成,并写入配置
|
||||||
|
return render_template('painting.html', data=build_data(), web_status=1)
|
||||||
|
else:
|
||||||
|
# Github 静态
|
||||||
|
# 数据需要生成,并写入静态文件
|
||||||
|
html_data = render_template('painting.html', data=build_data(), web_status=0)
|
||||||
|
with open("static/index.html", "w") as f:
|
||||||
|
f.write(html_data)
|
||||||
|
|
||||||
|
return 'OK'
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host='0.0.0.0', port=7777, debug=True)
|
28
requirements.txt
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
beautifulsoup4==4.12.2
|
||||||
|
blinker==1.6.3
|
||||||
|
certifi==2023.7.22
|
||||||
|
charset-normalizer==3.3.1
|
||||||
|
click==8.1.7
|
||||||
|
feedparser==6.0.10
|
||||||
|
Flask==3.0.0
|
||||||
|
idna==3.4
|
||||||
|
itsdangerous==2.1.2
|
||||||
|
jieba==0.42.1
|
||||||
|
Jinja2==3.1.2
|
||||||
|
joblib==1.3.2
|
||||||
|
loguru==0.7.2
|
||||||
|
lunardate==0.2.0
|
||||||
|
MarkupSafe==2.1.3
|
||||||
|
nltk==3.8.1
|
||||||
|
python-dateutil==2.8.2
|
||||||
|
pytz==2023.3.post1
|
||||||
|
regex==2023.10.3
|
||||||
|
requests==2.31.0
|
||||||
|
sgmllib3k==1.0.0
|
||||||
|
six==1.16.0
|
||||||
|
snownlp==0.12.3
|
||||||
|
soupsieve==2.5
|
||||||
|
textblob==0.17.1
|
||||||
|
tqdm==4.66.1
|
||||||
|
urllib3==2.0.7
|
||||||
|
Werkzeug==3.0.1
|
0
src/__init__.py
Normal file
122
src/analyzer.py
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import jieba.analyse
|
||||||
|
import pytz
|
||||||
|
from dateutil.parser import parse
|
||||||
|
from loguru import logger
|
||||||
|
from lunardate import LunarDate
|
||||||
|
from snownlp import SnowNLP
|
||||||
|
|
||||||
|
|
||||||
|
# 计算文本内容情感分数
|
||||||
|
def analyze_sentiment(text):
|
||||||
|
"""
|
||||||
|
博客文章情感分计算(有点问题,酌情使用)
|
||||||
|
:param text:文章文本
|
||||||
|
:return:分数
|
||||||
|
"""
|
||||||
|
s = SnowNLP(text)
|
||||||
|
return round(s.sentiments * 100)
|
||||||
|
|
||||||
|
|
||||||
|
def classify_and_extract_keywords(text: str, topK: int, stopwords: str,
|
||||||
|
tech_terms_file: str) -> tuple[None, list[Any]] | tuple[int, Any]:
|
||||||
|
"""
|
||||||
|
博客文章关键字提取
|
||||||
|
:param text:文章文本
|
||||||
|
:param topK:关键字数量,建议20个
|
||||||
|
:param stopwords:停词文本,去掉无意义词组
|
||||||
|
:param tech_terms_file:专业词语,区分文章类目
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
jieba.analyse.set_stop_words(stopwords)
|
||||||
|
keywords = jieba.analyse.extract_tags(text, topK=topK)
|
||||||
|
except ValueError as e:
|
||||||
|
logger.error(f"关键词提取出错:{e}")
|
||||||
|
return None, []
|
||||||
|
except ModuleNotFoundError as e:
|
||||||
|
logger.error(f"关键词提取出错:{e}")
|
||||||
|
return None, []
|
||||||
|
|
||||||
|
with open(tech_terms_file, 'r', encoding='utf-8') as f:
|
||||||
|
tech_terms_set = {line.strip().lower() for line in f}
|
||||||
|
|
||||||
|
for keyword in keywords:
|
||||||
|
if keyword.lower() in tech_terms_set:
|
||||||
|
return 1, keywords
|
||||||
|
|
||||||
|
return 2, keywords
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_weight(time_str: str):
|
||||||
|
"""
|
||||||
|
博客文章特殊日期权重分数计算。
|
||||||
|
- 传统节假日 +10
|
||||||
|
- 节假日 +7
|
||||||
|
- 凌晨 +5
|
||||||
|
- 早上 +4
|
||||||
|
- 下午 +3
|
||||||
|
- 晚上 +2
|
||||||
|
:param time_str: 时间字符串
|
||||||
|
:return:总分数,特殊日期
|
||||||
|
"""
|
||||||
|
dt = parse(time_str)
|
||||||
|
dt = dt.astimezone(pytz.timezone('Asia/Shanghai'))
|
||||||
|
|
||||||
|
weight = 0
|
||||||
|
date_str = ""
|
||||||
|
|
||||||
|
# 农历节日权重计算
|
||||||
|
LUNAR_HOLIDAYS = {
|
||||||
|
(1, 1): '春节',
|
||||||
|
(1, 15): '元宵节',
|
||||||
|
(2, 2): '龙抬头',
|
||||||
|
(5, 5): '端午节',
|
||||||
|
(7, 7): '七夕节',
|
||||||
|
(7, 15): '中元节',
|
||||||
|
(8, 15): '中秋节',
|
||||||
|
(9, 9): '重阳节',
|
||||||
|
(12, 8): '腊八节',
|
||||||
|
(12, 23): '小年',
|
||||||
|
(12, 30): '除夕'
|
||||||
|
}
|
||||||
|
|
||||||
|
lunar_date = LunarDate.fromSolarDate(dt.year, dt.month, dt.day)
|
||||||
|
if (lunar_date.month, lunar_date.day) in LUNAR_HOLIDAYS:
|
||||||
|
weight += 10
|
||||||
|
date_str = LUNAR_HOLIDAYS[(lunar_date.month, lunar_date.day)]
|
||||||
|
|
||||||
|
# 公历节日权重计算
|
||||||
|
SOLAR_HOLIDAYS = {
|
||||||
|
(1, 1): '元旦',
|
||||||
|
(2, 14): '情人节',
|
||||||
|
(3, 8): '国际妇女节',
|
||||||
|
(4, 4): '清明节',
|
||||||
|
(5, 1): '国际劳动节',
|
||||||
|
(10, 1): '国庆节',
|
||||||
|
(12, 13): '南京大屠杀纪念日',
|
||||||
|
(9, 18): '九一八事变纪念日',
|
||||||
|
(12, 7): '南京保卫战胜利纪念日',
|
||||||
|
(8, 15): '抗日战争胜利纪念日'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dt.month, dt.day) in SOLAR_HOLIDAYS:
|
||||||
|
weight += 7
|
||||||
|
date_str = SOLAR_HOLIDAYS[(dt.month, dt.day)]
|
||||||
|
|
||||||
|
if 22 <= dt.hour or dt.hour < 7:
|
||||||
|
weight += 5
|
||||||
|
elif 7 <= dt.hour < 12:
|
||||||
|
weight += 4
|
||||||
|
elif 12 <= dt.hour < 18:
|
||||||
|
weight += 3
|
||||||
|
elif 18 <= dt.hour < 22:
|
||||||
|
weight += 2
|
||||||
|
else:
|
||||||
|
weight += 0
|
||||||
|
|
||||||
|
if not date_str:
|
||||||
|
date_str = f"{dt.month}月{dt.day}日"
|
||||||
|
|
||||||
|
return weight, date_str
|
114
src/config.py
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
import configparser
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
from src.tools import check_website_status
|
||||||
|
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
def __init__(self, path):
|
||||||
|
"""
|
||||||
|
初始化配置文件 config.ini
|
||||||
|
:param path:文件路径
|
||||||
|
"""
|
||||||
|
if not os.path.isfile(path):
|
||||||
|
logger.error(f"配置文件 {path} 不存在或不是一个文件")
|
||||||
|
raise FileNotFoundError
|
||||||
|
|
||||||
|
self.path = path
|
||||||
|
self.config = configparser.ConfigParser()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.config.read(self.path)
|
||||||
|
except configparser.ParsingError as e:
|
||||||
|
logger.error(f"解析配置文件 {self.path} 错误: {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
except PermissionError as e:
|
||||||
|
logger.error(f"没有权限读取配置文件 {self.path}: {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
logger.info(f"配置文件 {self.path} 加载成功")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def rss_url(self):
|
||||||
|
try:
|
||||||
|
url = self.config.get('blog', 'rss', fallback=None)
|
||||||
|
except configparser.NoSectionError:
|
||||||
|
logger.error('未找到 blog 配置项,请检查拼写')
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not url:
|
||||||
|
logger.debug('rss 文件配置值为空,尝试读取环境变量')
|
||||||
|
url = os.environ.get('rss')
|
||||||
|
if url is None:
|
||||||
|
logger.error('rss 文件配置值为空,环境变量为空……')
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 如果网址不可访问,返回 None
|
||||||
|
if not check_website_status(url):
|
||||||
|
logger.error(f"rss URL {url} 不可访问")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return url
|
||||||
|
|
||||||
|
@property
|
||||||
|
def rss_domain(self):
|
||||||
|
rss_url = self.rss_url
|
||||||
|
|
||||||
|
if rss_url is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
parsed = urlparse(rss_url)
|
||||||
|
domain_parts = parsed.netloc.split('.')
|
||||||
|
|
||||||
|
if len(domain_parts) < 2:
|
||||||
|
logger.error(f"提供的 URL {rss_url} 的域名格式错误")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return '.'.join(domain_parts[-2:])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def blog_data(self):
|
||||||
|
try:
|
||||||
|
data = self.config.get('blog', 'data', fallback=None)
|
||||||
|
except configparser.NoSectionError:
|
||||||
|
logger.error('未找到 section 配置项,请检查拼写')
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
logger.error('data 配置值为空')
|
||||||
|
return None
|
||||||
|
|
||||||
|
return json.loads(data)
|
||||||
|
|
||||||
|
@blog_data.setter
|
||||||
|
def blog_data(self, value):
|
||||||
|
if not self.config.has_section('blog'):
|
||||||
|
self.config.add_section('blog')
|
||||||
|
|
||||||
|
self.config.set('blog', 'data', json.dumps(value))
|
||||||
|
|
||||||
|
with open(self.path, 'w') as configfile:
|
||||||
|
self.config.write(configfile)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def web_status(self):
|
||||||
|
try:
|
||||||
|
web_status = self.config.get('default', 'web', fallback=None)
|
||||||
|
except configparser.NoSectionError:
|
||||||
|
logger.error('未找到 web 配置项,请检查拼写')
|
||||||
|
return None
|
||||||
|
|
||||||
|
if web_status is None:
|
||||||
|
logger.error('web 配置值为空')
|
||||||
|
return True
|
||||||
|
|
||||||
|
if web_status == "True" or web_status == "true":
|
||||||
|
return True
|
||||||
|
|
||||||
|
if web_status == "False" or web_status == "false":
|
||||||
|
return False
|
95
src/generator.py
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
from collections import Counter
|
||||||
|
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
from .analyzer import analyze_sentiment, calculate_weight, classify_and_extract_keywords
|
||||||
|
from .config import Config
|
||||||
|
from .scraper import Blog
|
||||||
|
|
||||||
|
|
||||||
|
def build_data():
|
||||||
|
"""
|
||||||
|
目前只有一个主题,构建数据部分后期会再进行重构拆分
|
||||||
|
:return: 网页渲染数据
|
||||||
|
"""
|
||||||
|
# 读取配置
|
||||||
|
config = Config("config.ini")
|
||||||
|
|
||||||
|
# 创建博客对象
|
||||||
|
try:
|
||||||
|
my_blog = Blog(config.rss_url)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Feed 无法创建博客对象: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
logger.debug(my_blog)
|
||||||
|
|
||||||
|
# 构建博客基本数据
|
||||||
|
data = {
|
||||||
|
"blog_name": my_blog.title,
|
||||||
|
"blog_link": my_blog.link,
|
||||||
|
"blog_article_count": my_blog.article_count,
|
||||||
|
"blog_article_word_count": my_blog.article_word_count,
|
||||||
|
}
|
||||||
|
|
||||||
|
if my_blog.life is None:
|
||||||
|
data.update({
|
||||||
|
"blog_life": 0
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
data.update({
|
||||||
|
"blog_life_year": my_blog.life // 365,
|
||||||
|
"blog_life_day": my_blog.life % 365,
|
||||||
|
})
|
||||||
|
|
||||||
|
# 博客文章处理
|
||||||
|
for i, post in enumerate(my_blog.post_lists(), 1):
|
||||||
|
# 情感分
|
||||||
|
post.score = analyze_sentiment(post.content)
|
||||||
|
# 分类, 关键字
|
||||||
|
post.category, post.keys = classify_and_extract_keywords(text=post.content, topK=21,
|
||||||
|
stopwords='data/stop_words.txt',
|
||||||
|
tech_terms_file='data/tech_terms.txt')
|
||||||
|
# 权重, 日子计算
|
||||||
|
post.weight, post.date = calculate_weight(post.time)
|
||||||
|
|
||||||
|
logger.info(f"Post #{i}:")
|
||||||
|
logger.info(post)
|
||||||
|
|
||||||
|
# 博客文章权重计算
|
||||||
|
weights = [post.weight for post in my_blog.post_lists()]
|
||||||
|
max_weight = max(weights)
|
||||||
|
max_item = [post for post in my_blog.post_lists() if post.weight == max_weight][0]
|
||||||
|
|
||||||
|
data.update({
|
||||||
|
"blog_title": max_item.title,
|
||||||
|
"blog_content": max_item.content[0:50],
|
||||||
|
"blog_content_date": max_item.date,
|
||||||
|
})
|
||||||
|
|
||||||
|
# 暂时只有一个主题
|
||||||
|
# 博客关键词计算 5 个
|
||||||
|
all_keys = []
|
||||||
|
for post in my_blog.post_lists():
|
||||||
|
all_keys.extend(post.keys)
|
||||||
|
|
||||||
|
keyword_counts = Counter(all_keys)
|
||||||
|
top_keywords = keyword_counts.most_common(5)
|
||||||
|
data.update({
|
||||||
|
"blog_top_keywords": top_keywords
|
||||||
|
})
|
||||||
|
|
||||||
|
# 博客分类计算
|
||||||
|
categories = [post.category for post in my_blog.post_lists()]
|
||||||
|
cat_counts = Counter(categories)
|
||||||
|
most_common_cat = cat_counts.most_common(1)[0][0]
|
||||||
|
|
||||||
|
data.update({
|
||||||
|
"blog_category": "技术" if most_common_cat == 1 else "生活"
|
||||||
|
})
|
||||||
|
|
||||||
|
# 输出
|
||||||
|
logger.debug(data)
|
||||||
|
# 写入 config.ini 避免重复计算
|
||||||
|
config.blog_data = data
|
||||||
|
return data
|
153
src/scraper.py
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
import feedparser
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
from . import tools
|
||||||
|
|
||||||
|
|
||||||
|
class Blog:
|
||||||
|
def __init__(self, url):
|
||||||
|
try:
|
||||||
|
self.feed = feedparser.parse(url)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f'解析 RSS feed 时发生错误: {str(e)}')
|
||||||
|
raise
|
||||||
|
self.posts = [Post(entry) for entry in self.feed.entries]
|
||||||
|
|
||||||
|
def _get_feed_field(self, field):
|
||||||
|
"""
|
||||||
|
从 RSS feed 中获取特定字段
|
||||||
|
"""
|
||||||
|
field_value = self.feed.feed.get(field)
|
||||||
|
if field_value is None:
|
||||||
|
logger.warning(f'{field} 字段不存在!')
|
||||||
|
return field_value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def title(self):
|
||||||
|
return self._get_feed_field('title')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def link(self):
|
||||||
|
return self._get_feed_field('link')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def life(self):
|
||||||
|
domain = tools.get_domain(self.link)
|
||||||
|
return tools.get_domain_life(domain)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def article_count(self):
|
||||||
|
return len(self.posts)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def article_word_count(self):
|
||||||
|
return sum(post.word_count for post in self.posts)
|
||||||
|
|
||||||
|
def post_lists(self):
|
||||||
|
return self.posts
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"Blog: {self.title}, Life:{self.life}, Count{self.article_count}. Word count:{self.article_word_count}"
|
||||||
|
|
||||||
|
|
||||||
|
class Post:
|
||||||
|
def __init__(self, entry):
|
||||||
|
# 日期权重
|
||||||
|
self._weight = None
|
||||||
|
# 日子
|
||||||
|
self._date = None
|
||||||
|
# 情感分
|
||||||
|
self._score = None
|
||||||
|
# 关键字
|
||||||
|
self._keys = None
|
||||||
|
# 分类
|
||||||
|
self._category = None
|
||||||
|
self.entry = entry
|
||||||
|
|
||||||
|
def _get_entry_field(self, field):
|
||||||
|
"""
|
||||||
|
从 RSS entry 中获取特定字段
|
||||||
|
"""
|
||||||
|
field_value = self.entry.get(field)
|
||||||
|
if field_value is None:
|
||||||
|
pass
|
||||||
|
# logger.warning(f'{field} 字段不存在!')
|
||||||
|
return field_value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def title(self):
|
||||||
|
return self._get_entry_field('title')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def content(self):
|
||||||
|
description = self._get_entry_field('description')
|
||||||
|
content = self._get_entry_field('content')
|
||||||
|
if content:
|
||||||
|
content = content[0].get('value', '')
|
||||||
|
|
||||||
|
description = tools.remove_html_tags(description) if description else ""
|
||||||
|
content = tools.remove_html_tags(content) if content else ""
|
||||||
|
|
||||||
|
if len(description) < 128 and content:
|
||||||
|
return content
|
||||||
|
else:
|
||||||
|
return description
|
||||||
|
|
||||||
|
@property
|
||||||
|
def time(self):
|
||||||
|
return self._get_entry_field('published')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def link(self):
|
||||||
|
return self._get_entry_field('link')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def word_count(self):
|
||||||
|
return len(self.content) if self.content else 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def keys(self):
|
||||||
|
return self._keys
|
||||||
|
|
||||||
|
@keys.setter
|
||||||
|
def keys(self, value):
|
||||||
|
self._keys = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def score(self):
|
||||||
|
return self._score
|
||||||
|
|
||||||
|
@score.setter
|
||||||
|
def score(self, value):
|
||||||
|
self._score = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def category(self):
|
||||||
|
return self._category
|
||||||
|
|
||||||
|
@category.setter
|
||||||
|
def category(self, value):
|
||||||
|
self._category = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def date(self):
|
||||||
|
return self._date
|
||||||
|
|
||||||
|
@date.setter
|
||||||
|
def date(self, value):
|
||||||
|
self._date = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def weight(self):
|
||||||
|
return self._weight
|
||||||
|
|
||||||
|
@weight.setter
|
||||||
|
def weight(self, value):
|
||||||
|
self._weight = value
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return (f"Post title={self.title[:20]}..., "
|
||||||
|
f" content={self.content[:20]}..., "
|
||||||
|
f" time={self.time}, "
|
||||||
|
f" link={self.link}, "
|
||||||
|
f" word_count={self.word_count}")
|
99
src/tools.py
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
|
||||||
|
def check_website_status(url):
|
||||||
|
"""
|
||||||
|
检测网站是否可以正常访问,取决于 status == 200
|
||||||
|
:param url:网址
|
||||||
|
:return:True 可以访问,False 不可以。
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
response = requests.get(url, timeout=5) # Set timeout to 5 seconds
|
||||||
|
if response.status_code == 200:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
logger.error(f"{url} 网站无法访问,状态码:{response.status_code}")
|
||||||
|
return False
|
||||||
|
except requests.Timeout as e:
|
||||||
|
logger.error(f"{url} 请求超时,错误:{e}")
|
||||||
|
return False
|
||||||
|
except requests.ConnectionError as e:
|
||||||
|
logger.error(f"{url} 连接错误,错误:{e}")
|
||||||
|
return False
|
||||||
|
except requests.RequestException as e:
|
||||||
|
logger.error(f"{url} 网站无法访问,错误:{e}")
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"{url} 未知错误,错误:{e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def get_domain(url):
|
||||||
|
"""
|
||||||
|
获取 url 注册域名,二级域名 + 顶级域名
|
||||||
|
:param url:url 地址
|
||||||
|
:return:注册域名
|
||||||
|
"""
|
||||||
|
parsed_uri = urlparse(url)
|
||||||
|
subdomain = parsed_uri.netloc.split('.')[-2] # 获取二级域名部分
|
||||||
|
top_domain = parsed_uri.netloc.split('.')[-1] # 获取顶级域名部分
|
||||||
|
return f"{subdomain}.{top_domain}"
|
||||||
|
|
||||||
|
|
||||||
|
def get_domain_life(url):
|
||||||
|
"""
|
||||||
|
域名注册天数
|
||||||
|
:param url:注册域名
|
||||||
|
:return:天数
|
||||||
|
"""
|
||||||
|
headers = {
|
||||||
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"
|
||||||
|
}
|
||||||
|
domain_url = f"https://rdap.verisign.com/com/v1/domain/{url}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get(domain_url, headers=headers)
|
||||||
|
response.raise_for_status() # Raises stored HTTPError, if one occurred.
|
||||||
|
|
||||||
|
registration_date = response.json().get('events')[0].get('eventDate')
|
||||||
|
if registration_date is None:
|
||||||
|
logger.error("无效响应,未找到 'eventDate'")
|
||||||
|
return None
|
||||||
|
|
||||||
|
date_format = "%Y-%m-%dT%H:%M:%SZ"
|
||||||
|
|
||||||
|
# 将字符串转换为日期对象
|
||||||
|
your_date = datetime.strptime(registration_date, date_format)
|
||||||
|
|
||||||
|
# 当前日期
|
||||||
|
now = datetime.now() # 使用当前日期
|
||||||
|
|
||||||
|
# 计算天数差
|
||||||
|
delta = now - your_date
|
||||||
|
|
||||||
|
return delta.days
|
||||||
|
|
||||||
|
except requests.exceptions.HTTPError as err:
|
||||||
|
logger.error(f"HTTP 错误: {err}")
|
||||||
|
except requests.exceptions.RequestException as err:
|
||||||
|
logger.error(f"请求错误: {err}")
|
||||||
|
except ValueError as err:
|
||||||
|
logger.error(f"日期解析错误: {err}")
|
||||||
|
except Exception as err:
|
||||||
|
logger.error(f"未预期的错误: {err}")
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def remove_html_tags(text):
|
||||||
|
"""
|
||||||
|
移除无用 html 标签
|
||||||
|
:param text:源文本
|
||||||
|
:return:文本
|
||||||
|
"""
|
||||||
|
return BeautifulSoup(text, "html.parser").get_text()
|
BIN
static/endofyear.jpg
Normal file
After Width: | Height: | Size: 123 KiB |
7
static/painting/css/animate.min.css
vendored
Normal file
349
static/painting/css/normalize.css
vendored
Normal file
@ -0,0 +1,349 @@
|
|||||||
|
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
|
||||||
|
|
||||||
|
/* Document
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the line height in all browsers.
|
||||||
|
* 2. Prevent adjustments of font size after orientation changes in iOS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
html {
|
||||||
|
line-height: 1.15; /* 1 */
|
||||||
|
-webkit-text-size-adjust: 100%; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sections
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the margin in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the `main` element consistently in IE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
main {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the font size and margin on `h1` elements within `section` and
|
||||||
|
* `article` contexts in Chrome, Firefox, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
margin: 0.67em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grouping content
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Add the correct box sizing in Firefox.
|
||||||
|
* 2. Show the overflow in Edge and IE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
hr {
|
||||||
|
box-sizing: content-box; /* 1 */
|
||||||
|
height: 0; /* 1 */
|
||||||
|
overflow: visible; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||||
|
* 2. Correct the odd `em` font sizing in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pre {
|
||||||
|
font-family: monospace, monospace; /* 1 */
|
||||||
|
font-size: 1em; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text-level semantics
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the gray background on active links in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
a {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Remove the bottom border in Chrome 57-
|
||||||
|
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abbr[title] {
|
||||||
|
border-bottom: none; /* 1 */
|
||||||
|
text-decoration: underline; /* 2 */
|
||||||
|
text-decoration: underline dotted; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||||
|
* 2. Correct the odd `em` font sizing in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
code,
|
||||||
|
kbd,
|
||||||
|
samp {
|
||||||
|
font-family: monospace, monospace; /* 1 */
|
||||||
|
font-size: 1em; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct font size in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||||
|
* all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sub,
|
||||||
|
sup {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Embedded content
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the border on images inside links in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
img {
|
||||||
|
border-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forms
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Change the font styles in all browsers.
|
||||||
|
* 2. Remove the margin in Firefox and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
optgroup,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
font-family: inherit; /* 1 */
|
||||||
|
font-size: 100%; /* 1 */
|
||||||
|
line-height: 1.15; /* 1 */
|
||||||
|
margin: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the overflow in IE.
|
||||||
|
* 1. Show the overflow in Edge.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input { /* 1 */
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||||
|
* 1. Remove the inheritance of text transform in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
select { /* 1 */
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the inability to style clickable types in iOS and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
[type="button"],
|
||||||
|
[type="reset"],
|
||||||
|
[type="submit"] {
|
||||||
|
-webkit-appearance: button;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inner border and padding in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button::-moz-focus-inner,
|
||||||
|
[type="button"]::-moz-focus-inner,
|
||||||
|
[type="reset"]::-moz-focus-inner,
|
||||||
|
[type="submit"]::-moz-focus-inner {
|
||||||
|
border-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore the focus styles unset by the previous rule.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button:-moz-focusring,
|
||||||
|
[type="button"]:-moz-focusring,
|
||||||
|
[type="reset"]:-moz-focusring,
|
||||||
|
[type="submit"]:-moz-focusring {
|
||||||
|
outline: 1px dotted ButtonText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the padding in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
padding: 0.35em 0.75em 0.625em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the text wrapping in Edge and IE.
|
||||||
|
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||||
|
* 3. Remove the padding so developers are not caught out when they zero out
|
||||||
|
* `fieldset` elements in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
legend {
|
||||||
|
box-sizing: border-box; /* 1 */
|
||||||
|
color: inherit; /* 2 */
|
||||||
|
display: table; /* 1 */
|
||||||
|
max-width: 100%; /* 1 */
|
||||||
|
padding: 0; /* 3 */
|
||||||
|
white-space: normal; /* 1 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||||
|
*/
|
||||||
|
|
||||||
|
progress {
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the default vertical scrollbar in IE 10+.
|
||||||
|
*/
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Add the correct box sizing in IE 10.
|
||||||
|
* 2. Remove the padding in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="checkbox"],
|
||||||
|
[type="radio"] {
|
||||||
|
box-sizing: border-box; /* 1 */
|
||||||
|
padding: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="number"]::-webkit-inner-spin-button,
|
||||||
|
[type="number"]::-webkit-outer-spin-button {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the odd appearance in Chrome and Safari.
|
||||||
|
* 2. Correct the outline style in Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="search"] {
|
||||||
|
-webkit-appearance: textfield; /* 1 */
|
||||||
|
outline-offset: -2px; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inner padding in Chrome and Safari on macOS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="search"]::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||||
|
* 2. Change font properties to `inherit` in Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
::-webkit-file-upload-button {
|
||||||
|
-webkit-appearance: button; /* 1 */
|
||||||
|
font: inherit; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interactive
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the correct display in Edge, IE 10+, and Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
details {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the correct display in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
summary {
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Misc
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in IE 10+.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
227
static/painting/css/painting.css
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'wenkai';
|
||||||
|
src: url('../font/LXGWWenKaiMonoGB-Bold.ttf') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 320px) {
|
||||||
|
html {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 55vh;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 320px) and (max-width: 480px) {
|
||||||
|
html {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 55vh;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 480px) and (max-width: 768px) {
|
||||||
|
html {
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 55vh;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
html {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 55vh;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-family: 'wenkai', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
|
||||||
|
'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
|
||||||
|
'Noto Color Emoji';
|
||||||
|
|
||||||
|
letter-spacing: 0.25rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: none;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 375px;
|
||||||
|
height: 100vh;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#tab1 {
|
||||||
|
background-image: url('../img/page1.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab2 {
|
||||||
|
background-image: url('../img/page2.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab2-box {
|
||||||
|
position: fixed;
|
||||||
|
top: 1rem;
|
||||||
|
padding: 1rem 1rem;
|
||||||
|
font-size: 1.75rem;
|
||||||
|
color: #FFFFFFD9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab2-box > p > small {
|
||||||
|
line-height: 3rem;
|
||||||
|
font-size: 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab3 {
|
||||||
|
background-image: url('../img/page3.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab3-box {
|
||||||
|
position: fixed;
|
||||||
|
top: 1rem;
|
||||||
|
padding: 1rem 1rem;
|
||||||
|
font-size: 1.75rem;
|
||||||
|
color: #ffa940;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab3-box > p > small {
|
||||||
|
line-height: 3rem;
|
||||||
|
font-size: 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab4 {
|
||||||
|
background-image: url('../img/page4.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab4-box {
|
||||||
|
writing-mode: vertical-lr;
|
||||||
|
position: fixed;
|
||||||
|
top: 2rem;
|
||||||
|
font-size: 1.75rem;
|
||||||
|
color: #FFFFFFD9;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab4 > .tab4-box > p:last-child {
|
||||||
|
writing-mode: horizontal-tb;
|
||||||
|
margin: 0 0;
|
||||||
|
height: 30vh;
|
||||||
|
width: 13rem;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#tab5 {
|
||||||
|
background-image: url('../img/page5.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab5-box {
|
||||||
|
position: relative;
|
||||||
|
top: 2rem;
|
||||||
|
left: 0.75rem;
|
||||||
|
color: #597ef7;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab5 > .tab5-box > p:nth-child(1) {
|
||||||
|
position: relative;
|
||||||
|
top: -6rem;
|
||||||
|
left: 0.8rem;
|
||||||
|
transform: rotate(-43deg);
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab5 > .tab5-box > p:nth-child(2) {
|
||||||
|
position: relative;
|
||||||
|
top: 3.2rem;
|
||||||
|
left: 7.8rem;
|
||||||
|
transform: rotate(42deg);
|
||||||
|
font-size: 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab5 > .tab5-box > p:nth-child(3) {
|
||||||
|
position: relative;
|
||||||
|
top: 8rem;
|
||||||
|
left: 2rem;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab5 > .tab5-box > p:nth-child(4) {
|
||||||
|
position: relative;
|
||||||
|
top: -13rem;
|
||||||
|
left: 11.7rem;
|
||||||
|
transform: rotate(-50deg);
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab5 > .tab5-box > p:nth-child(5) {
|
||||||
|
position: relative;
|
||||||
|
top: -5.6rem;
|
||||||
|
left: 9.7rem;
|
||||||
|
transform: rotate(-50deg);
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab5 > .tab5-box > p:nth-child(6) {
|
||||||
|
position: relative;
|
||||||
|
top: 2rem;
|
||||||
|
left: 2rem;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab5 > .tab5-box > p:nth-child(6) > small {
|
||||||
|
font-size: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab5 > .tab5-box > p:nth-child(7) {
|
||||||
|
position: relative;
|
||||||
|
top: 2rem;
|
||||||
|
left: 2rem;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab5 > .tab5-box > p:nth-child(7) > small {
|
||||||
|
font-size: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#tab6 {
|
||||||
|
background-image: url('../img/page6.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab6 > .tab6-box {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 7%;
|
||||||
|
padding-left: 2rem;
|
||||||
|
font-size: 1.75rem;
|
||||||
|
color: #FFFFFFD9;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab7 {
|
||||||
|
background-image: url('../img/page7.jpg');
|
||||||
|
}
|
||||||
|
|
BIN
static/painting/font/LXGWWenKaiMonoGB-Bold.ttf
Normal file
BIN
static/painting/img/page1.jpg
Normal file
After Width: | Height: | Size: 266 KiB |
BIN
static/painting/img/page2.jpg
Normal file
After Width: | Height: | Size: 312 KiB |
BIN
static/painting/img/page3.jpg
Normal file
After Width: | Height: | Size: 426 KiB |
BIN
static/painting/img/page4.jpg
Normal file
After Width: | Height: | Size: 332 KiB |
BIN
static/painting/img/page5.jpg
Normal file
After Width: | Height: | Size: 418 KiB |
BIN
static/painting/img/page6.jpg
Normal file
After Width: | Height: | Size: 448 KiB |
BIN
static/painting/img/page7.jpg
Normal file
After Width: | Height: | Size: 490 KiB |
104
templates/painting.html
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>EndOfYear</title>
|
||||||
|
{% if web_status == 1 %}
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='painting/css/normalize.css') }}">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='painting/css/animate.min.css') }}">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='painting/css/painting.css') }}">
|
||||||
|
{% else %}
|
||||||
|
<link rel="stylesheet" href="painting/css/normalize.css">
|
||||||
|
<link rel="stylesheet" href="painting/css/animate.min.css">
|
||||||
|
<link rel="stylesheet" href="painting/css/painting.css">
|
||||||
|
{% endif %}
|
||||||
|
<script async src="https://umami.7wate.org/script.js" data-website-id="635fec50-bc6c-4ac2-909a-e2a7403438be"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container active animate__animated animate__fadeIn animate__slow" id="tab1"></div>
|
||||||
|
<div class="container animate__animated animate__fadeIn animate__slow" id="tab2">
|
||||||
|
<div class="tab2-box">
|
||||||
|
<p class="animate__animated animate__fadeIn animate__delay-1s">亲爱的{{ data.blog_name }}</p>
|
||||||
|
{% if data.blog_life == 0 %}
|
||||||
|
<p class="animate__animated animate__fadeIn animate__delay-2s">旧事如梦,一年已过</p>
|
||||||
|
<p class="animate__animated animate__fadeIn animate__delay-2s">贰三年、感谢有你!</p>
|
||||||
|
{% else %}
|
||||||
|
<p class="animate__animated animate__fadeIn animate__delay-2s">今天是我们相识的</p>
|
||||||
|
<p class="animate__animated animate__fadeIn animate__delay-3s">第 <small>{{ data.blog_life_year }}</small> 年
|
||||||
|
<small>{{ data.blog_life_day }}</small> 天</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="container animate__animated animate__fadeIn animate__slow" id="tab3">
|
||||||
|
<div class="tab3-box">
|
||||||
|
<p class="animate__animated animate__fadeInUp animate__delay-1s">这一年你写下了</p>
|
||||||
|
<p class="animate__animated animate__fadeInUp animate__delay-2s"><small>{{ data.blog_article_count }}</small>
|
||||||
|
篇博文</p>
|
||||||
|
<p class="animate__animated animate__fadeInUp animate__delay-3s"><small>{{ data.blog_article_word_count
|
||||||
|
}}</small> 个文字</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container animate__animated animate__fadeIn animate__slow" id="tab4">
|
||||||
|
<div class="tab4-box">
|
||||||
|
<p class="animate__animated animate__fadeInDown animate__delay-1s">{{ data.blog_content_date }}那天,你写下了</p>
|
||||||
|
<p class="animate__animated animate__fadeInDown animate__delay-2s">{{ data.blog_title }}</p>
|
||||||
|
<p class="animate__animated animate__fadeInDown animate__delay-3s">{{ data.blog_content }}<small>……</small>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container animate__animated animate__fadeIn animate__slow" id="tab5">
|
||||||
|
<div class="tab5-box">
|
||||||
|
{% for keyword in data.blog_top_keywords %}
|
||||||
|
<p>{{ keyword[0] }}</p>
|
||||||
|
{% endfor %}
|
||||||
|
<p class="animate__animated animate__fadeInDown animate__delay-1s">这些都是<small>你</small>的</p>
|
||||||
|
<p class="animate__animated animate__fadeInDown animate__delay-2s">专属<small>关键词</small></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container animate__animated animate__fadeIn animate__slow" id="tab6">
|
||||||
|
<div class="tab6-box">
|
||||||
|
<p class="animate__animated animate__fadeInLeft animate__delay-1s">热爱{{ data.blog_category }}的你</p>
|
||||||
|
<p class="animate__animated animate__fadeInLeft animate__delay-2s">一定要继续砥砺前行!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container animate__animated animate__fadeIn animate__slow" id="tab7">
|
||||||
|
<div class="tab7-box">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
console.log("Window inner size: ", window.innerWidth, "x", window.innerHeight);
|
||||||
|
console.log("Window outer size: ", window.outerWidth, "x", window.outerHeight);
|
||||||
|
console.log("Screen size: ", screen.width, "x", screen.height);
|
||||||
|
console.log("Screen available size: ", screen.availWidth, "x", screen.availHeight);
|
||||||
|
var carousel = {
|
||||||
|
currentIndex: 0,
|
||||||
|
tabs: [],
|
||||||
|
|
||||||
|
init: function () {
|
||||||
|
this.tabs = document.getElementsByClassName('container');
|
||||||
|
|
||||||
|
for (let i = 0; i < this.tabs.length; i++) {
|
||||||
|
this.tabs[i].addEventListener('click', () => {
|
||||||
|
this.next();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
next: function () {
|
||||||
|
this.tabs[this.currentIndex].classList.remove('active');
|
||||||
|
this.currentIndex = (this.currentIndex + 1) % this.tabs.length;
|
||||||
|
this.tabs[this.currentIndex].classList.add('active');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.onload = function () {
|
||||||
|
carousel.init();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|