Wow! Number 400. What a milestone for CAS(E) This Sketch. Congratulations! I used this week's sketch for another Christmas card.
The images are from Altenew's Holiday Bow and the gray glitter strips are from a paper pack by DCWV. I used a darker gray from the same pack for the branches. The sentiment is from HLS..
Appell sequence
In mathematics, an Appell sequence, named after Paul Émile Appell, is any polynomial sequence {pn(x)}n = 0, 1, 2, ... satisfying the identity
\( {d \over dx} p_n(x) = np_{n-1}(x), \)
and in which p0(x) is a non-zero constant.
Among the most notable Appell sequences besides the trivial example { xn } are the Hermite polynomials, the Bernoulli polynomials, and the Euler polynomials. Every Appell sequence is a Sheffer sequence, but most Sheffer sequences are not Appell sequences.
Equivalent characterizations of Appell sequences
The following conditions on polynomial sequences can easily be seen to be equivalent:
For n = 1, 2, 3, ...,
\( {d \over dx} p_n(x) = np_{n-1}(x) \)
and p0(x) is a non-zero constant;
For some sequence {cn}n = 0, 1, 2, ... of scalars with c0 ≠ 0,
\( p_n(x) = \sum_{k=0}^n {n \choose k} c_k x^{n-k}; \)
For the same sequence of scalars,
\( p_n(x) = \left(\sum_{k=0}^\infty {c_k \over k!} D^k\right) x^n, \)
where
D = {d \over dx};
For n = 0, 1, 2, ...,
p_n(x+y) = \sum_{k=0}^n {n \choose k} p_k(x) y^{n-k}.
Recursion formula
Suppose
\( p_n(x) = \left(\sum_{k=0}^\infty {c_k \over k!} D^k\right) x^n = Sx^n, \)
where the last equality is taken to define the linear operator S on the space of polynomials in x. Let
\( T = S^{-1} = \left(\sum_{k=0}^\infty {c_k \over k!} D^k\right)^{-1} = \sum_{k=1}^\infty {a_k \over k!} D^k \)
be the inverse operator, the coefficients ak being those of the usual reciprocal of a formal power series, so that
\( Tp_n(x) = x^n.\, \)
In the conventions of the umbral calculus, one often treats this formal power series T as representing the Appell sequence {pn}. One can define
\( \log T = \log\left(\sum_{k=0}^\infty {a_k \over k!} D^k \right) \)
by using the usual power series expansion of the log(1 + x) and the usual definition of composition of formal power series. Then we have
\( p_{n+1}(x) = (x - (\log T)')p_n(x).\, \)
(This formal differentiation of a power series in the differential operator D is an instance of Pincherle differentiation.)
In the case of Hermite polynomials, this reduces to the conventional recursion formula for that sequence.
Subgroup of the Sheffer polynomials
The set of all Appell sequences is closed under the operation of umbral composition of polynomial sequences, defined as follows. Suppose { pn(x) : n = 0, 1, 2, 3, ... } and { qn(x) : n = 0, 1, 2, 3, ... } are polynomial sequences, given by
\( p_n(x)=\sum_{k=0}^n a_{n,k}x^k\ \mbox{and}\ q_n(x)=\sum_{k=0}^n b_{n,k}x^k. \)
Then the umbral composition p o q is the polynomial sequence whose nth term is
\( (p_n\circ q)(x)=\sum_{k=0}^n a_{n,k}q_k(x)=\sum_{0\le k \le \ell \le n} a_{n,k}b_{k,\ell}x^\ell \)
(the subscript n appears in pn, since this is the n term of that sequence, but not in q, since this refers to the sequence as a whole rather than one of its terms).
Under this operation, the set of all Sheffer sequences is a non-abelian group, but the set of all Appell sequences is an abelian subgroup. That it is abelian can be seen by considering the fact that every Appell sequence is of the form
\( p_n(x) = \left(\sum_{k=0}^\infty {c_k \over k!} D^k\right) x^n, \)
and that umbral composition of Appell sequences corresponds to multiplication of these formal power series in the operator D.
Different convention
Another convention followed by some authors (see Chihara) defines this concept in a different way, conflicting with Appell's original definition, by using the identity
\( {d \over dx} p_n(x) = p_{n-1}(x) \)
instead.
See also
Sheffer sequence
Umbral calculus
Generalized Appell polynomials
Wick product
References
Paul Appell, "Sur une classe de polynômes", Annales scientifiques de l'École Normale Supérieure 2e série, tome 9, 1880.
Steven Roman and Gian-Carlo Rota, "The Umbral Calculus", Advances in Mathematics, volume 27, pages 95 – 188, (1978).
G.-C. Rota, D. Kahaner, and A. Odlyzko, "Finite Operator Calculus", Journal of Mathematical Analysis and its Applications, vol. 42, no. 3, June 1973. Reprinted in the book with the same title, Academic Press, New York, 1975.
Steven Roman. The Umbral Calculus. Dover Publications.
Theodore Seio Chihara (1978). An Introduction to Orthogonal Polynomials. Gordon and Breach, New York. ISBN 0-677-04150-0.
External links
Appell Sequence at MathWorld
Retrieved from "http://en.wikipedia.org/"
All text is available under the terms of the GNU Free Documentation License
Ikea
+Category:
Autor:
Words:
How a Construction Contractor Improved My Home
++ For many years, I wasn't really happy with the property I was living in. I thought that the kitchen was too small. I hated trying to cook family meals as it was super stressful in such a tiny space. I used to dream about selling the house and buying somewhere new, but I didn't really have the money and I didn't want to move area with my kids still in school. My friend suggested that I hire a team of construction contractors and ask them to extend the kitchen space out into the backyard. The contractors were great. They demolished one wall and then laid a new foundation for the extension. Next, the walls were constructed and then the roof was installed. I am so happy with my new kitchen. +
++ +
2018
+-
+
-
+++
Tips to Ensure Safe DIY Removal of Non-Friable Asbestos From Your Home
+ +
++ It is always best to you hire an asbestos removal professional when you need to remove asbestos from your abode. But if you only need to remove a small amount of firmly-bound asbestos that does not require you to obtain an asbestos removal permit, then you can take on the project yourself provided you take the necessary safety measures. Here are a number of effective safety practices to follow when removing non-friable asbestos from your house.
+[Read More] +
+
-
+
-
+++
How to strengthen your home's foundation against flood damage
+ +
++ If you live in a flood-prone area, your foundation may need extra strength against floodwaters. The foundation should also be strengthened against storm surges, strong winds, and heavy flows of water. In this way, your home is likely to experience less damage when a hurricane or tornado strikes. +There are several ways through which you can strengthen your home's foundation. Some foundation work is more complex than others, so make sure you determine the level of strength that your property needs.
+[Read More] +
+
-
+
-
+++
What are the Evident Signs that Your Building Needs Underpinning?
+ +
++ Problems with a building's foundation can affect its ability to endure the stress and weight of the entire structure. If you don't take immediate measures to stabilise the foundation, you will end up with even costlier repairs. Alternatively, you may choose to demolish the structure, especially if the amount of repair work is too costly and involved. That's why you need to look out for the following signs that indicate your foundation could be experiencing some damage.
+[Read More] +
+
-
+
-
+++
Home Improvement: Simple Renovations Tips for a Small Budget
+ +
++ Renovating your home can be an expensive undertaking, and the costs can get out of control, causing unexpected complications. Therefore, if you are planning on improving your home, you should prepare a suitable budget. Financial planning will help you manage your spending and avoid exceeding your means. Unfortunately, your resources might be limited even if you create a good budget. If you are worried about the total cost for the renovation work, you should use the outlined guidelines to keep your expenses in check.
+[Read More] +
+
-
+
-
+++
Survey Services - Why You Should Invest In Drone Technology
+ +
++ Before you can embark on construction on your lot, one of the most critical assessments to have done is a topographical land survey. This survey is essential to enlighten your contractors on the state of the land before they can begin developing it. It typically is conducted manually and is a long and arduous process to ensure precise mapping out of the property. However, as tech advances, there is an advanced method of doing this through drones.
+[Read More] +
+
-
+
-
+++
Everything That's Great About Metal Roofs
+ +
++ Without a doubt, metal is one of the most beneficial roofing materials available. Compared to other alternatives, there is a lot that is cool about metal roofs. Firstly, the savings on air conditioning will be significant. That's right; a metal roof will make your home cooler and save you on AC costs. As metal roofing contractors will confirm, the secret to how energy efficient a metal roof will be lies in the finishing chosen.
+[Read More] +
+
-
+
-
+++
Exploring Various Types of Tennis Court Surfaces
+ +
++ Since 1859, tennis has been a popular sport played in many different areas around the world. In current times, tennis features some of the world's most lucrative tournaments, such as the U.S Open, the French Open, and the Australian Open. Fans of tennis enjoy emulating top athletes such as Rodger Federer, Serena Williams and Rafael Nadal, just to name a few. +While the dimensions of a tennis court are typically standard, the playing surfaces differ significantly.
+[Read More] +
+
-
+
-
+++
Grin And Bore It: The Many Ways Using Bore Water Can Lower Your Farm's Water Bills
+ +
++ Of the many concerns a farmer has to deal with as they go about the day-to-day business of running their farms, one of the most important is the amount of water their business consumes. All varieties of farm, from crop-growing operations to livestock ranches, use prodigious amounts of water for various tasks, and if all of that water is drawn from centralised, government-owned sources, the costs of using it can add up very quickly.
+[Read More] +
+
-
+
-
+++
How to repair chipped areas of your kerb
+ +
++ Many people fear to deal with concrete kerbs because it seems like one of the most complicated building materials to operate. However, there are times when it becomes close to impossible to avoid making minor repairs on your concrete, especially when the kerb has served you for some years, and it is starting to disintegrate. One of the common damages that happen to kerbs as they age is that they start chipping.
+[Read More] +
+
-
+
-
+++
How piling ensures a stable foundation for your building
+ +
++ A strong foundation is essential to support your building. Whether you want to create a new build property or just add a room to an existing building you need to be sure that what you build will stand the test of time. Before you start building work it is important that you begin with a detailed survey of your land to ensure it is stable enough to support your building. If any issues are highlighted by the survey you should discuss the results with a qualified building professional who will be able to guide you towards the most appropriate solutions.
+[Read More] +
+
The Magicians and Magic Hub
Who is in your Top 3 Mentalists of all time?
This topic has 4 replies, 2 voices, and was last updated 1 year agoby .
- You must be logged in to reply to this topic.
+ + +
+ + +| · | ++ + 国学四人谈:从孟子… + + | +2018/05/20 |
| · | ++ + 深切的悼念,永恒的… + + | +2018/05/09 |
| · | ++ + 【唐明邦先生纪念专… + + | +2018/05/08 |
| · | ++ + 【唐明邦先生纪念专… + + | +2018/05/08 |
| · | ++ + 珞珈佛学讲坛:《禅… + + | +2018/04/24 |
| · | ++ + 2018届“方太青竹简… + + | +2018/06/10 |
| · | ++ + 深切的悼念,永恒的… + + | +2018/05/07 |
| · | ++ + 讣告——唐明邦先生… + + | +2018/05/07 |
| · | ++ + “弘毅学堂”国学班… + + | +2017/11/14 |
| · | ++ + 武汉大学国学院“弘… + + | +2017/09/25 |
| · | ++ + 【楚天都市报】于亭… + + | +2018/06/22 |
| · | ++ + 【光明日报】郭齐勇… + + | +2018/06/22 |
| · | ++ + 【澎湃新闻】专访武… + + | +2018/06/22 |
| · | ++ + 【文汇报】郭齐勇:… + + | +2018/06/22 |
| · | ++ + 【文汇讲堂】“接着… + + | +2018/06/22 |
Copyright?2014 武汉大学国学院版权所有 All Rights Reserved. 地址:中国·武汉·珞珈山 邮编:430072
+|
+ РУС |
+|
| + | +|
| + + + + | ++ |
+Thermo+ + |
++ |
+ ![]() |
+ + | ++ | +
+
+ + + |
| + | |||
+
+
+
|
+
+
+
+
+
+
+
+ +AIT Associated Repository of Academic Resources > + + ++ Browsing by Author 中村, 栄治 ++ + + + + +
+
+
+
+
+ Showing results 5 to 24 of 37
+
+
+
+ < previous
+ next >
+
+
+
+
+ Showing results 5 to 24 of 37
+
+
+
+ < previous
+ next >
+
+
+
+
+ + |
+
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
|
+ ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+ ![]() |
+ + | ++ | +
+
+ + + |
| + | |||
+
+
+
|
+
+
+
+
+
+
+
+ +AIT Associated Repository of Academic Resources > + + ++ Browsing by Author 中村, 栄治 ++ + + + + +
+
+
+
+
+ Showing results 5 to 24 of 37
+
+
+
+ < previous
+ next >
+
+
+
+
+ Showing results 5 to 24 of 37
+
+
+
+ < previous
+ next >
+
+
+
+
+ + |
+
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
|
+ ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
henryspace @henryspace发展大了的电报毕竟也要受监管,凡是中心化的东西都逃不脱要被控制的命运;但是太自由了也很容易玩脱了,成为作恶和犯罪的温床,所以区块链这种东西注定也只是小众的,只要有人群在的地方,人们不允许有不能被控制的东西任意发展。
北野 @alimy好熟悉的app啊,看👀其logo,就好像哪见过,之前好像有开源版本来着?后来被zoom给收购了? 忘了,可能搞混了吧~
北野 @alimy@henryspace端到端加密 说实话也并不是大众群体的刚性需求,这玩意说以开发商的角度思考,就TM的一个好噱头,方便讲故事拉投资顺便拉点用户。 +站在普通大众群体,端密聊天,可有可无,老子又不是名人,也没人说我是帅哥美女,除了对面的聊天对象,谁tm在乎老子啊,都不在乎了,还怕你吖的看老子聊啥啊,不存在的~ 所以端密聊天,大众群体是概念模糊的,有选择当然更好,没得选也不太在乎~ +
yanjun @yanjun新的练手项目get

+ +
+
+
+
+ + + + |
+
+
+
+
+
+
+
+
+
++ +
+
+
+
+
+
+
+
++ + |
+
+
+
+
+
+
+
+ + + + +
+ + + + |
+
+
+
Вас могут заинтересовать:
Подснежник, стихотворения для детей и юношества (1897 г.)
-
+
Автор: Плещеев А.Н.
@@ -180,8 +180,10 @@ П Р О Д А Н О
Формат книги: 150 х 220 мм
Твердый переплет
-
Плещеев Алексей Николаевич (1825-1893 гг.) - русский писатель, поэт, переводчик; литературный и театральный критик. В 1846 году первый же сборник стихов сделал Плещеева знаменитым в революционной молодежной среде; как участник кружка Петрашевского он был в 1849 году арестован и некоторое время спустя отправлен в ссылку, где провел на военной службе почти десять лет. По возвращении из ссылки Плещеев продолжил литературную деятельность; пройдя через годы бедности и лишений, он стал авторитетным литератором, критиком, издателем, а в конце жизни и меценатом. Многие произведения поэта (особенно - стихи для детей) стали хрестоматийными, считаются классикой. На стихи Плещеева известнейшими русскими композиторами написаны более ста романсов.
-
+
Плещеев Алексей Николаевич (1825-1893 гг.) - русский писатель, поэт, переводчик; литературный и театральный критик. В 1846 году первый же сборник стихов сделал Плещеева знаменитым в революционной молодежной среде; как участник кружка Петрашевского он был в 1849 году арестован и некоторое время спустя отправлен в ссылку, где провел на военной службе почти десять лет. По возвращении из ссылки Плещеев продолжил литературную деятельность; пройдя через годы бедности и лишений, он стал авторитетным литератором, критиком, издателем, а в конце жизни и меценатом. Многие произведения поэта (особенно - стихи для детей) стали хрестоматийными, считаются классикой. На стихи Плещеева известнейшими русскими композиторами написаны более ста романсов.
+
+
+
Купив старинную книгу, изданную более 100 лет назад, вы станете обладателем антикварного издания, которое не подлежит вывозу за пределы Российской Федерации
@@ -243,7 +245,8 @@ Му
- Антикварная книга во владельческом составном переплете. Золотое тиснением по корешку. Потертости переплета. Следы реставрации двух страниц (изображения Колизея). На титульном листе старой книги библиотечный штамп. Следы загрязнения страниц. Лисьи пятна. Следы загрязнения страниц от перелистывания. Редкие следы залития. Мелкие надрывы и фрагментарные утраты по краям некоторых страниц (текст не задет). Книготорговые штампы и пометы на нахзаце. Реставрация бумажной полосой стр. 53 (текст незначительно задет). Издание шестое. Исторический рассказ для детей. Орфография и пунктуация приближены к современным нормам. Первая публикация произведения состоялась в 1890 году, "Мученики Колизея" тогда были напечатаны в Университетской типографии.
+ Антикварная книга во владельческом составном переплете. Золотое тиснением по корешку. Потертости переплета. Следы реставрации двух страниц (изображения Колизея). На титульном листе старой книги библиотечный штамп. Следы загрязнения страниц. Лисьи пятна. Следы загрязнения страниц от перелистывания. Редкие следы залития. Мелкие надрывы и фрагментарные утраты по краям некоторых страниц (текст не задет). Книготорговые штампы и пометы на нахзаце. Реставрация бумажной полосой стр. 53 (текст незначительно задет). Издание шестое. Исторический рассказ для детей. Орфография и пунктуация приближены к современным нормам. Первая публикация произведения состоялась в 1890 году, "Мученики Колизея" тогда были напечатаны в Университетской типографии.
+
Издательство: Типография Г. Лисснера и Д. Собко (Москва)
Язык: русский
diff --git a/tests/llm_web_kit/main_html_parser/parser/test_layout_parser.py b/tests/llm_web_kit/main_html_parser/parser/test_layout_parser.py
index c7a4df5f..3eaf8471 100644
--- a/tests/llm_web_kit/main_html_parser/parser/test_layout_parser.py
+++ b/tests/llm_web_kit/main_html_parser/parser/test_layout_parser.py
@@ -163,7 +163,7 @@ def test_dynamic_id(self):
template_source = re.sub('post-37041', 'test-37041', template_source)
expand_source = re.sub('test-37041', 'test-25031', template_source)
# 简化网页
- simplified_html, typical_raw_tag_html, _ = simplify_html(template_source)
+ simplified_html, typical_raw_tag_html = simplify_html(template_source)
# 模型结果格式改写
llm_path = base_dir.joinpath(TEST_CASES[0]['input'][2][0])
llm_response = json.loads(llm_path.read_text(encoding='utf-8'))
@@ -203,7 +203,7 @@ def test_dynamic_classid(self):
expand_source2 = re.sub('testid-25031', '', expand_source)
template_source2 = re.sub('testid-37041', '', template_source)
# 简化网页
- simplified_html, typical_raw_tag_html, _ = simplify_html(template_source)
+ simplified_html, typical_raw_tag_html = simplify_html(template_source)
# 模型结果格式改写
llm_path = base_dir.joinpath(TEST_CASES[0]['input'][2][0])
llm_response = json.loads(llm_path.read_text(encoding='utf-8'))
@@ -226,7 +226,7 @@ def test_dynamic_classid(self):
assert 'Permalink link a questo articolo' not in main_html_body and 'Con la stesura di un' in main_html_body
# 简化网页
- simplified_html, typical_raw_tag_html, _ = simplify_html(template_source2)
+ simplified_html, typical_raw_tag_html = simplify_html(template_source2)
# 模型结果格式改写
llm_path = base_dir.joinpath(TEST_CASES[0]['input'][2][0])
llm_response = json.loads(llm_path.read_text(encoding='utf-8'))
@@ -268,7 +268,7 @@ def test_more_noise_enable(self):
new_p.text = 'test more noise'
expand_source = html.tostring(tree, encoding='utf-8').decode()
# 简化网页
- simplified_html, typical_raw_tag_html, _ = simplify_html(template_source)
+ simplified_html, typical_raw_tag_html = simplify_html(template_source)
# 模型结果格式改写
llm_path = base_dir.joinpath(TEST_CASES[0]['input'][2][0])
llm_response = json.loads(llm_path.read_text(encoding='utf-8'))
@@ -305,7 +305,7 @@ def test_classid_with_first_class(self):
template_source = re.sub('post-37041', '', template_source)
expand_source = re.sub('post-classid', 'post-classid template-classid', template_source)
# 简化网页
- simplified_html, typical_raw_tag_html, _ = simplify_html(template_source)
+ simplified_html, typical_raw_tag_html = simplify_html(template_source)
# 模型结果格式改写
llm_path = base_dir.joinpath(TEST_CASES[0]['input'][2][0])
llm_response = json.loads(llm_path.read_text(encoding='utf-8'))
@@ -385,7 +385,7 @@ def test_incomplete_tag(self):
# 模型结果格式改写
llm_path = 'assets/input_layout_batch_parser/test_incomplete_tag.json'
llm_response = json.loads(base_dir.joinpath(llm_path).read_text(encoding='utf-8'))
- simplified_html, typical_raw_tag_html, _ = simplify_html(html_source)
+ simplified_html, typical_raw_tag_html = simplify_html(html_source)
pre_data = {'typical_raw_tag_html': typical_raw_tag_html, 'typical_raw_html': html_source,
'llm_response': llm_response}
pre_data = PreDataJson(pre_data)
diff --git a/tests/llm_web_kit/main_html_parser/parser/test_tag_simplifier.py b/tests/llm_web_kit/main_html_parser/parser/test_tag_simplifier.py
index ea5d57e9..45962b1e 100644
--- a/tests/llm_web_kit/main_html_parser/parser/test_tag_simplifier.py
+++ b/tests/llm_web_kit/main_html_parser/parser/test_tag_simplifier.py
@@ -1,6 +1,9 @@
+import re
import unittest
from pathlib import Path
+from lxml import html
+
from llm_web_kit.input.pre_data_json import PreDataJson, PreDataJsonKey
from llm_web_kit.main_html_parser.parser.tag_simplifier import \
HtmlTagSimplifierParser
@@ -9,60 +12,465 @@
class MyTestCase(unittest.TestCase):
+ def check_and_find_max_item_id(self, input_str: str) -> int:
+ # 匹配所有 _item_id="XXX" 的模式,提取XXX部分
+ pattern = "_item_id" + r'="(\d+)"'
+ matches = re.findall(pattern, input_str)
+
+ # 至少匹配一个
+ if len(matches) == 0:
+ return 0
+
+ # 匹配到的对象全部转化为int
+ int_list = []
+ for match in matches:
+ try:
+ int_list.append(int(match))
+ except Exception:
+ raise ValueError(f'error while convert match {match} to int')
+
+ # 检查是否为从1开始的连续整数
+ target_value = 1
+ for int_id in int_list:
+ if int_id == target_value:
+ target_value += 1
+ else:
+ raise ValueError(
+ f'mistake find in int list, current target value is {target_value}, but find {int_id}' + '\n' + input_str
+ )
+
+ # 都没有问题的情况下,返回最大的数
+ return int_list[-1]
+
def test_tag_simplifier(self):
file_path = base_dir / 'assets/test_html_data/test_tah_simplifier.html'
with open(file_path, 'r', encoding='utf-8') as file:
raw_html = file.read()
+
data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html}
pre_data = PreDataJson(data_dict)
+
pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
- _item_id_count = simplifier_raw_html.count('_item_id')
- self.assertEqual(_item_id_count, 32)
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 34)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
def test_tag_simplifier1(self):
file_path = base_dir / 'assets/test_html_data/normal_dl.html'
with open(file_path, 'r', encoding='utf-8') as file:
raw_html = file.read()
+
data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html}
pre_data = PreDataJson(data_dict)
+
pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
- _item_id_count = simplifier_raw_html.count('_item_id')
- self.assertEqual(_item_id_count, 18)
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 48)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
def test_tag_simplifier2(self):
file_path = base_dir / 'assets/test_html_data/normal_table.html'
with open(file_path, 'r', encoding='utf-8') as file:
raw_html = file.read()
+
data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html}
pre_data = PreDataJson(data_dict)
+
pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
- _item_id_count = simplifier_raw_html.count('_item_id')
- self.assertEqual(_item_id_count, 30)
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 11)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
def test_tag_simplifier3(self):
file_path = base_dir / 'assets/test_html_data/special_table_1.html'
with open(file_path, 'r', encoding='utf-8') as file:
raw_html = file.read()
+
data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html}
pre_data = PreDataJson(data_dict)
+
pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
- _item_id_count = simplifier_raw_html.count('_item_id')
- self.assertEqual(_item_id_count, 66)
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 41)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
def test_tag_simplifier4(self):
file_path = base_dir / 'assets/test_html_data/1.html'
with open(file_path, 'r', encoding='utf-8') as file:
raw_html = file.read()
+
data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html, PreDataJsonKey.IS_XPATH: False}
pre_data = PreDataJson(data_dict)
+
+ pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
+ simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 113)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
+
+ def test_tag_simplifier_table(self):
+ file_path = base_dir / 'assets/test_html_data/simplify_cases/table.html'
+ with open(file_path, 'r', encoding='utf-8') as file:
+ raw_html = file.read()
+
+ data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html}
+ pre_data = PreDataJson(data_dict)
+
+ pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
+ simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 35)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
+
+ id_dom = html.fromstring(raw_tag_html)
+ # 用xpath定位data-anno-uid="anno-uid-3vtzg9uxee4"的table元素,该table用于布局
+ table_element = id_dom.xpath('//table[@data-anno-uid="anno-uid-3vtzg9uxee4"]')[0]
+ # 确认该table元素没有_item_id属性
+ self.assertEqual(table_element.get('_item_id'), None)
+ # 确认该table的3个td元素的内部都包含若干个存在_item_id属性的元素
+ for td_element in table_element.xpath('./tbody/tr/td'):
+ td_item_count = 0
+ for child in td_element.iter():
+ if child.get('_item_id') is not None:
+ td_item_count += 1
+ self.assertNotEqual(td_item_count, 0)
+
+ def test_tag_simplifier_data_table(self):
+ file_path = base_dir / 'assets/test_html_data/simplify_cases/data_table.html'
+ with open(file_path, 'r', encoding='utf-8') as file:
+ raw_html = file.read()
+
+ data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html}
+ pre_data = PreDataJson(data_dict)
+
+ pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
+ simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 105)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
+
+ id_dom = html.fromstring(raw_tag_html)
+ # 用xpath定位带有data-table属性的table元素
+ table_element = id_dom.xpath('//table[@data-table]')[0]
+ # 确认该table元素有_item_id属性
+ self.assertIsNotNone(table_element.get('_item_id'))
+
+ def test_tag_simplifier_nested_table_colgroup(self):
+ file_path = base_dir / 'assets/test_html_data/simplify_cases/nested_table_colgroup.html'
+ with open(file_path, 'r', encoding='utf-8') as file:
+ raw_html = file.read()
+
+ data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html}
+ pre_data = PreDataJson(data_dict)
+
+ pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
+ simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 13)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
+
+ id_dom = html.fromstring(raw_tag_html)
+ # 用xpath定位外层table元素,该table用于布局
+ table_element = id_dom.xpath('//table[@class="centralPane"]')[0]
+ # 确认该table元素没有_item_id属性
+ self.assertIsNone(table_element.get('_item_id'))
+
+ # 用xpath定位内层table元素,该table是数据表格,
标签内存在colgroup元素
+ table_element = id_dom.xpath('//table[@class="miscTable"]')[0]
+ # 确认该table元素有_item_id属性
+ self.assertIsNotNone(table_element.get('_item_id'))
+
+ def test_tag_simplifier_nested_table_headers(self):
+ # 测试表格的单元格中包含headers属性的情况,这个测试用例中的表格单元格存在headers属性,但是标签内不包含colgroup元素
+ file_path = base_dir / 'assets/test_html_data/simplify_cases/nested_table_headers.html'
+ with open(file_path, 'r', encoding='utf-8') as file:
+ raw_html = file.read()
+
+ data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html}
+ pre_data = PreDataJson(data_dict)
+
+ pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
+ simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 13)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
+
+ id_dom = html.fromstring(raw_tag_html)
+ # 用xpath定位外层table元素,该table用于布局
+ table_element = id_dom.xpath('//table[@class="centralPane"]')[0]
+ # 确认该table元素没有_item_id属性
+ self.assertIsNone(table_element.get('_item_id'))
+
+ # 用xpath定位内层table元素,该table是数据表格,其单元格包含headers属性
+ table_element = id_dom.xpath('//table[@class="miscTable"]')[0]
+ # 确认该table元素有_item_id属性
+ self.assertIsNotNone(table_element.get('_item_id'))
+
+ def test_tag_simplifier_nested_table_caption(self):
+ file_path = base_dir / 'assets/test_html_data/simplify_cases/nested_table_caption.html'
+ with open(file_path, 'r', encoding='utf-8') as file:
+ raw_html = file.read()
+
+ data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html}
+ pre_data = PreDataJson(data_dict)
+
+ pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
+ simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 14)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
+
+ id_dom = html.fromstring(raw_tag_html)
+ # 用xpath定位外层table元素,该table用于布局
+ table_element = id_dom.xpath('//table[@data-anno-uid="anno-uid-xgzpvn8fnqk"]')[0]
+ # 确认该table元素没有_item_id属性
+ self.assertIsNone(table_element.get('_item_id'))
+
+ # 用xpath定位内层table元素,该table是数据表格,其包含caption元素
+ table_element = id_dom.xpath('//table[@data-anno-uid="anno-uid-olo3onur84"]')[0]
+ # 确认该table元素有_item_id属性
+ self.assertIsNotNone(table_element.get('_item_id'))
+
+ def test_tag_simplifier_list(self):
+ file_path = base_dir / 'assets/test_html_data/simplify_cases/list.html'
+ with open(file_path, 'r', encoding='utf-8') as file:
+ raw_html = file.read()
+
+ data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html}
+ pre_data = PreDataJson(data_dict)
+
+ pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
+ simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 118)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
+
+ id_dom = html.fromstring(raw_tag_html)
+ # 用xpath定位ul元素,该ul用于布局
+ list_element = id_dom.xpath('//ul[@data-anno-uid="anno-uid-7s58m3hrcz5"]')[0]
+ # 确认该ul元素没有_item_id属性
+ self.assertIsNone(list_element.get('_item_id'))
+ # 确认该ul元素下的li元素内均包含有_item_id属性的元素
+ for li_element in list_element.xpath('./li'):
+ li_item_count = 0
+ for child in li_element.iter():
+ if child.get('_item_id') is not None:
+ li_item_count += 1
+ self.assertNotEqual(li_item_count, 0)
+
+ def test_tag_simplifier_non_list_child(self):
+ file_path = base_dir / 'assets/test_html_data/simplify_cases/non_list_child.html'
+ with open(file_path, 'r', encoding='utf-8') as file:
+ raw_html = file.read()
+
+ data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html}
+ pre_data = PreDataJson(data_dict)
+
+ pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
+ simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 151)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
+
+ id_dom = html.fromstring(raw_tag_html)
+ # 用xpath定位ul元素,该ul用于布局
+ list_element = id_dom.xpath('//ul[@data-anno-uid="anno-uid-myobddy8ord"]')[0]
+ # 确认该ul元素没有_item_id属性
+ self.assertIsNone(list_element.get('_item_id'))
+ # 用xpath定位上述ul内部的一个li,该li内部结构复杂,应该包含多个_item_id
+ li_element = id_dom.xpath('//li[@data-anno-uid="anno-uid-7wux77fqc7t"]')[0]
+ li_item_count = 0
+ for child in li_element.iter():
+ if child.get('_item_id') is not None:
+ li_item_count += 1
+ self.assertNotEqual(li_item_count, 0)
+
+ def test_tag_simplifier_inline_block(self):
+ file_path = base_dir / 'assets/test_html_data/simplify_cases/inline_block.html'
+ with open(file_path, 'r', encoding='utf-8') as file:
+ raw_html = file.read()
+
+ data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html}
+ pre_data = PreDataJson(data_dict)
+
pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
- _item_id_count = simplifier_raw_html.count('_item_id')
- self.assertEqual(_item_id_count, 51)
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 12)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
+
+ id_dom = html.fromstring(raw_tag_html)
+ # 用xpath定位span元素,该span内部包含了块级元素
+ span_element = id_dom.xpath('//span[@data-anno-uid="anno-uid-yrlyp4ay0l"]')[0]
+ # 确认该span元素没有_item_id属性
+ self.assertIsNone(span_element.get('_item_id'))
+ # 该span元素内部包含多个块级元素,每个块级元素都包含_item_id属性
+ for child in span_element.iterchildren():
+ self.assertIsNotNone(child.get("_item_id"))
+
+ def test_tag_simplifier_abnormal_comment(self):
+ file_path = base_dir / 'assets/test_html_data/simplify_cases/abnormal_comment.html'
+ with open(file_path, 'r', encoding='utf-8') as file:
+ raw_html = file.read()
+
+ data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html}
+ pre_data = PreDataJson(data_dict)
+
+ pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
+ simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 53)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
+
+ # 验证不规范的注释内包含的有效内容没有被删除
+ self.assertIn('', raw_tag_html)
+ # 验证规范的注释都已被删除
+ comment_res = re.search(r'', raw_tag_html, flags=re.DOTALL)
+ self.assertIsNone(comment_res)
+
+ def test_tag_simplifier_header_tag(self):
+ file_path = base_dir / 'assets/test_html_data/simplify_cases/header_tag.html'
+ with open(file_path, 'r', encoding='utf-8') as file:
+ raw_html = file.read()
+
+ data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html}
+ pre_data = PreDataJson(data_dict)
+
+ pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
+ simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 35)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
+
+ id_dom = html.fromstring(raw_tag_html)
+ # 用xpath定位元素,该元素位于id名为header的元素内部,且这个'header'是body的直接子元素
+ header_element = id_dom.xpath('//h1[@data-anno-uid="anno-uid-g513k4pfha8"]')[0]
+ # 确认该元素有_item_id属性,也就是被保留了
+ self.assertIsNotNone(header_element.get('_item_id'))
+ # 用xpath定位元素,该元素位于header标签内部,但这个header不是body的直接子元素
+ header_element = id_dom.xpath('//h2[@data-anno-uid="anno-uid-g8cyd0j0kn6"]')[0]
+ # 确认该元素有_item_id属性,也被保留了(目前的simplify是所有的header都保留)
+ self.assertIsNotNone(header_element.get('_item_id'))
+
+ def test_tag_simplifier_nav_class(self):
+ file_path = base_dir / 'assets/test_html_data/simplify_cases/nav_class.html'
+ with open(file_path, 'r', encoding='utf-8') as file:
+ raw_html = file.read()
+
+ data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html}
+ pre_data = PreDataJson(data_dict)
+
+ pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
+ simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 58)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
+
+ id_dom = html.fromstring(raw_tag_html)
+ # 用xpath定位元素,该元素的class是nav,但不是body的直接子元素,应该保留
+ nav_element = id_dom.xpath('//div[@data-anno-uid="anno-uid-v6mugwj7iv"]')[0]
+ # 验证nav内部有_item_id属性的元素,证明nav没有被删除
+ nav_item_count = 0
+ for child in nav_element.iter():
+ if child.get('_item_id') is not None:
+ nav_item_count += 1
+ self.assertNotEqual(nav_item_count, 0)
+
+ nav_element = id_dom.xpath('//div[@data-anno-uid="anno-uid-189mlskr0fc"]')[0]
+ self.assertIsNone(nav_element.get("_item_id"))
+
+ def test_tag_simplifier_block_select(self):
+ file_path = base_dir / 'assets/test_html_data/simplify_cases/block_select.html'
+ with open(file_path, 'r', encoding='utf-8') as file:
+ raw_html = file.read()
+
+ data_dict = {PreDataJsonKey.TYPICAL_RAW_HTML: raw_html}
+ pre_data = PreDataJson(data_dict)
+
+ pre_data_result = HtmlTagSimplifierParser({}).parse(pre_data)
+
+ simplifier_raw_html = pre_data_result.get(PreDataJsonKey.TYPICAL_SIMPLIFIED_HTML, '')
+ simple_id_count = self.check_and_find_max_item_id(simplifier_raw_html)
+ self.assertEqual(simple_id_count, 7)
+
+ raw_tag_html = pre_data_result.get(PreDataJsonKey.TYPICAL_RAW_TAG_HTML, '')
+ tag_id_count = self.check_and_find_max_item_id(raw_tag_html)
+ self.assertEqual(tag_id_count, simple_id_count)
+
+ id_dom = html.fromstring(raw_tag_html)
+ # 用xpath定位元素,该元素是块级元素且内部不包含块级元素,但该元素本身没有cc-select,只是其内部元素有cc-select
+ p_element = id_dom.xpath('//p[@data-anno-uid="anno-uid-tnbktgx26s"]')[0]
+ # 验证该元素被加上了_item_id和cc-select
+ self.assertIsNotNone(p_element.get("_item_id"))
+ self.assertIsNotNone(p_element.get("cc-select"))
if __name__ == '__main__':
@@ -180,8 +180,10 @@
П Р О Д А Н О
Формат книги: 150 х 220 ммТвердый переплет
-
Плещеев Алексей Николаевич (1825-1893 гг.) - русский писатель, поэт, переводчик; литературный и театральный критик. В 1846 году первый же сборник стихов сделал Плещеева знаменитым в революционной молодежной среде; как участник кружка Петрашевского он был в 1849 году арестован и некоторое время спустя отправлен в ссылку, где провел на военной службе почти десять лет. По возвращении из ссылки Плещеев продолжил литературную деятельность; пройдя через годы бедности и лишений, он стал авторитетным литератором, критиком, издателем, а в конце жизни и меценатом. Многие произведения поэта (особенно - стихи для детей) стали хрестоматийными, считаются классикой. На стихи Плещеева известнейшими русскими композиторами написаны более ста романсов.
-
+
Плещеев Алексей Николаевич (1825-1893 гг.) - русский писатель, поэт, переводчик; литературный и театральный критик. В 1846 году первый же сборник стихов сделал Плещеева знаменитым в революционной молодежной среде; как участник кружка Петрашевского он был в 1849 году арестован и некоторое время спустя отправлен в ссылку, где провел на военной службе почти десять лет. По возвращении из ссылки Плещеев продолжил литературную деятельность; пройдя через годы бедности и лишений, он стал авторитетным литератором, критиком, издателем, а в конце жизни и меценатом. Многие произведения поэта (особенно - стихи для детей) стали хрестоматийными, считаются классикой. На стихи Плещеева известнейшими русскими композиторами написаны более ста романсов. +
+ +
Купив старинную книгу, изданную более 100 лет назад, вы станете обладателем антикварного издания, которое не подлежит вывозу за пределы Российской Федерации




+
+


















+

+



+
+
+
+
+
+