tag:blogger.com,1999:blog-4944111245262046302024-03-08T13:32:29.159+02:00Compiled blogTranslation, interpretation, programming
traduceri autorizate germană engleză română BrașovTiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comBlogger508125tag:blogger.com,1999:blog-494411124526204630.post-70232907552505691922024-03-05T16:10:00.000+02:002024-03-05T16:10:17.213+02:00Barebone Quart API from Sqlite DB<p>import asyncio<br />import sqlite3<br />from quart import Quart<br /><br />app = Quart(__name__)<br /><br />async def connect_db():<br /> conn = sqlite3.connect("your_database.db")<br /> conn.row_factory = sqlite3.Row<br /> return conn<br /><br />async def fetch_data(column1):<br /> async with connect_db() as conn:<br /> cursor = conn.cursor()<br /> cursor.execute("SELECT ?, column2 FROM your_table", (column1,))<br /> data = cursor.fetchall()<br /> return [dict(row) for row in data]<br /><br />@app.route("/api/data/<column_name>")<br />async def get_data(column_name):<br /> data = await fetch_data(column_name)<br /> return data # Return the list of dictionaries directly<br /><br />if __name__ == "__main__":<br /> app.run(debug=True)<br /></p><p data-sourcepos="31:1-31:194">Here, the <code>get_data</code> function
directly returns the list of dictionaries obtained from the database,
and Quart automatically handles the serialization to JSON format before
sending the response.</p><p data-sourcepos="33:1-33:48">However, using <code>jsonify</code> offers some advantages:</p><ul data-sourcepos="35:1-37:0"><li data-sourcepos="35:1-35:142"><strong>Consistency:</strong> It provides a consistent way to handle different data structures, ensuring they are all converted to JSON format correctly.</li><li data-sourcepos="36:1-37:0"><strong>Customization:</strong> It allows
for additional options like specifying status codes, setting custom
headers, or customizing the JSON serialization if needed.</li></ul><p data-sourcepos="38:1-38:190">Therefore, while <code>jsonify</code>
isn't strictly required in this case, it can improve code clarity and
maintainability, especially for larger projects or when dealing with
diverse data structures.</p><p></p><p><i>or with jsonify (not necessary)</i></p><p></p><p>import asyncio<br />import sqlite3<br />from quart import Quart, jsonify<br /><br />app = Quart(__name__)<br /><br />async def connect_db():<br /> conn = sqlite3.connect("your_database.db")<br /> conn.row_factory = sqlite3.Row<br /> return conn<br /><br />async def fetch_data(column1):<br /> async with connect_db() as conn:<br /> cursor = conn.cursor()<br /> cursor.execute("SELECT ?, column2 FROM your_table", (column1,)) # Dynamic query<br /> data = cursor.fetchall()<br /> return [dict(row) for row in data]<br /><br />@app.route("/api/data/<column_name>")<br />async def get_data(column_name):<br /> data = await fetch_data(column_name)<br /> return jsonify(data)<br /><br />if __name__ == "__main__":<br /> app.run(debug=True)<br /></p><p data-sourcepos="37:1-37:15"><strong>How to Use:</strong></p><p data-sourcepos="39:1-39:97">Now, you would access the API by providing the first column name as part of the URL. For example:</p><ul data-sourcepos="41:1-43:0"><li data-sourcepos="41:1-41:63"><code>/api/data/name</code> (assuming the first column is named "name")</li><li data-sourcepos="42:1-43:0"><code>/api/data/age</code> (assuming the first column is named "age")</li></ul><p></p>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-84465770850634470292024-03-05T13:09:00.003+02:002024-03-06T09:41:11.737+02:00Informații E-Factura<p><span>Ministerul Finanţelor anunţă lansarea versiunii simplificate a aplicaţiei e-Factura. Ministrul de resort, Marcel Boloş, spune că aceasta este în primul rând utilă celor aproximativ 670.000 contribuabili mici care au nevoie de un format gratuit şi uşor de folosit.<br /><br />”În continuarea eforturilor de digitalizare şi simplificare a procedurilor fiscale, Ministerul Finanţelor anunţă lansarea versiunii simplificate a aplicaţiei e-Factura”, anunţă ministerul, potrivit News.ro</span></p><p><span>Versiunea îmbunătăţită vine cu o interfaţă intuitivă şi funcţionalităţi mai uşor de utilizat, astfel încât fiecare utilizator să poată emite facturi în conformitate cu cerinţele fiscale într-un mod rapid şi eficient.<br /><br />„Aşa cum am mai spus, fiecare îmbunătăţire adoptată a ţinut cont de nevoile semnalate de contribuabili. Am tot avut întâlniri cu reprezentaţii mediului de afaceri şi una dintre solicitările lor a fost aceasta. Versiunea simplificată a aplicaţiei e-Factura vine cu o serie de avantaje şi funcţionalităţi care vor face gestionarea facturilor mai uşoară şi mai accesibilă pentru toţi utilizatorii. Ne-am gândit în primul rând la cei aproximativ 670.000 contribuabili mici care trebuie să utilizeze sistemul şi au nevoie de o aplicaţie gratuită, intuitivă şi uşor de folosit. De asemenea, aplicaţia extinsă este acum disponibilă şi în limba engleză, urmând ca în perioada următoare să fie tradusă şi cea simplificată”, a explicat ministrul Marcel Boloş.</span></p><p><span>Aplicaţia web de completare a facturii într-un format simplificat răspunde solicitărilor venite din partea micorintreprinderilor, ce nu utilizează în mod curent elemente operaţionale complexe.<br /><br />A fost redesenată pentru a include automat ghidaje (i.e. codul tipului facturii este prestabilit la 380, codul monedei este exclusiv RON) şi bife pentru a afişa elementele de identificare obligatorii în funcţie de categoria de plătitor de TVA.<br /><br />Au fost restrânse nomenclatoarele de TVA la cele utilizate frecvent pentru tranzacţii domestice şi incluse procentele de taxă sub format selectabil.<br /><br />De asemenea, o nouă facilitate importantă adăugată sistemului este aplicaţia extinsă în limba engleză pentru contribuabilii nerezidenţi înregistraţi în scopuri de TVA ce au obligaţia de raportare a facturilor emise pentru livrări/prestări pe teritoriul României.</span></p><p><span>În situaţia în care sistemul naţional privind factura electronică RO e-Factura nu este funcţional timp de minimum 24 de ore, obligaţia de transmitere prevăzută la art.10 alin.(1) din Ordonanţa de urgenţă a Guvernului nr.120/2021 se suspendă până la repunerea în funcţiune a sistemului.<br /><br />Termenul-limită pentru transmiterea facturilor emise, pentru livrările de bunuri şi prestările de servicii care au locul livrării sau prestării în România, în sistemul naţional privind factura electronică RO e-Factura este de 5 zile lucrătoare (n.r. de la 1 iulie sunt 5 zile calendaristice) de la data emiterii facturii, dar nu mai târziu de 5 zile lucrătoare de la data-limită prevăzută pentru emiterea facturii la art.319 alin.(16) din Codul fiscal.<br /><br />În perioada 1 ianuarie - 31 martie 2024, nerespectarea termenului limită pentru transmiterea facturilor în sistemul naţional privind factura electronică RO e-Factura nu se sancţionează.</span></p><p><span>e-Factura va fi mai ușor de
folosit, spune ANAF, care face o aplicație care se adresează afacerilor
mici, cu puține facturi pe lună. Aplicația poate fi accesată de marți
dimineață, 5 martie 2024.</span></p><div class="content"><div class="moz-reader-content reader-show-element"><div class="page" id="readability-page-1"><div>
<p data-index="2">„Cuprinde doar elementele informaționale de bază, face
în mod automat și selecția tipului de factură. Pentru că se agresează
atât categoriei, cât și celor neplătitori de TVA. Se aplică o bifă,
practic este intuitiv aici, nu mai este lăsat la libera alegere”. <br /></p>
<p data-index="3">Aplicația simplificată e-Factura a fost creată pentru
cele peste 400.000 de afaceri mici, care emit puține facturi pe lună și
nu au nevoie de informații suplimentare, cum ar fi referințe de lot sau
de comandă pentru produse. Doar elementele obligatorii. Astfel că nu va
fi nevoie de un soft diferit de facturare, iar procesul va dura foarte
puțin, spun reprezentanții ANAF.</p>
<div data-index="4"><p>Aplicația va fi disponibilă pe site-ul Ministerul
de Finanțe și va avea un buton separat, dar rămâne și aplicația
obișnuită e-Factura.</p></div>
<p data-index="5">„Numărul lor este destul de consistent, mai ales
al celor care încă nu înțeleg că trebuie să utilizeze e-Factura și din
calculele noastre undeva între 150.000 și 200.000. Aceștia sunt primii
care vor primit aceste note de conformare. În caz contrar, riscă
amenzi”. Până pe 31 martie, cei care nu transmit facturi în
noul sistem nu vor fi sancționați. Ministerul analizează acum
posibilitatea ca acest termen de grație să se amâne până pe 1 iulie,
însă nu a fost luată o decizie până acum.</p><p data-index="5" style="text-align: center;">-----</p><p data-index="4">De la 1 ianuarie 2024 în relaţia business-to-business
(B2B), până în prezent, aproximativ 40 milioane de facturi au fost
înregistrate cu succes în sistemul e-Factura, în valoare totală de 397
miliarde de lei.</p>
<p data-index="5">Un aspect important pe care l-au semnalat
contribuabilii a fost imposibilitatea accesării sistemului în situaţiile
în care au loc lucrări de mentenanţă la nivelul Spaţiului Privat
Virtual (SPV). În acest sens, utilizarea e-Factura se poate face acum
direct de pe site-ul ANAF. Trebuie însă ca utilizatorul să aibă cont în
SPV, unde s-a înregistrat în baza certificatului digital.</p>
<p data-index="6">Potrivit comunicatului de pe site-ul ministerului, în
situaţia în care sistemul naţional privind factura electronică RO
e-Factura nu este funcțional timp de minimum 24 de ore, obligația de
transmitere prevăzută la art.10 alin.(1) din Ordonanţa de urgenţă a
Guvernului nr.120/2021 se suspendă până la repunerea în funcţiune a
sistemului.</p>
<p data-index="7">Termenul-limită pentru transmiterea facturilor emise,
pentru livrările de bunuri și prestările de servicii care au locul
livrării sau prestării în România, în sistemul național privind factura
electronică RO e-Factura este de 5 zile lucrătoare (n.r. de la 1 iulie
sunt 5 zile calendaristice) de la data emiterii facturii, dar nu mai
târziu de 5 zile lucrătoare de la data-limită prevăzută pentru emiterea
facturii la art.319 alin.(16) din Codul fiscal.</p>
<p data-index="8">În perioada 1 ianuarie - 31 martie 2024, nerespectarea
termenului limită pentru transmiterea facturilor în sistemul național
privind factura electronică RO e-Factura nu se sancționează.</p><p data-index="8" style="text-align: center;">-----</p><div class="content">
<div class="moz-reader-content reader-show-element"><div class="page" id="readability-page-1"><div data-index="1"><p>Ultima
noutate în ce privește e-Factura este că în sfârșit se poate face
automat conversia din XML în PDF, printr-o simplă apăsare de buton.
Ministrul a insistat mult pentru asta. Până acum conversia se făcea
manual, iar Finanțele au raportat și un milion de facturi pe zi. Sursele
noastre din Ministerul Finanțelor spun că îmbunătățirile pentru această
schimbare majoră de sistem de raportare a facturilor, <a data-skip-linkfix="1" href="https://www.digi24.ro/digieconomic/financiar/e-factura-este-obligatorie-de-la-1-ianuarie-2024-din-iulie-dispar-toate-celelalte-tipuri-de-facturi-1505">care a luat pe toată lumea prin surprindere</a>, se realizează constant.</p><p>Trecerea
la sistemul unic de raportare a facturilor în mediu electronic la ANAF a
întâmpinat o serie de probleme în aplicare, de la 1 ianuarie, când
e-Factura a devenit obligatorie în relațiile comerciale dintre firme.</p><p>E-Factura se aplică încă din 2022 pe relația firme - guvern. Dacă
firmele mari sau cele care au business cu statul erau obișnuite cu
birocrația și au găsit soluții să folosească sistemul așa cum a fost
făcut inițial<a data-skip-linkfix="1" href="https://www.digi24.ro/digieconomic/financiar/sef-anaf-in-razboi-cu-contabilii-mi-am-permis-luxul-sa-fac-dialog-pe-e-factura-daca-injura-este-problema-dansilor-9161">, trecerea la acest sistem pentru toate firmele a arătat slăbiciuni ale acestuia</a>.</p><p>A fost introdusă <a data-skip-linkfix="1" href="https://www.digi24.ro/digieconomic/financiar/e-factura-a-fost-introdusa-autofacturarea-termenul-de-depunere-creste-daca-sistemul-nu-functioneaza-8333">autofacturarea</a>.
Apoi, conform unui comunicat transmis de Ministerul Finanțelor,
începând cu 16 ianuarie 2024, sistemul e-Factura nu va mai permite
introducerea facturilor duplicat. Această măsură vine să crească
acuratețea și integritatea datelor înregistrate în sistem.<br />După
încărcarea facturii fără Spațiul Privat Virtual, s-a mai introdus
filtrarea pe categorii. Furnizorii de servicii de contabilitate au cerut
să poată filtra facturile în baza anumitor criterii specifice. Această
facilitate a fost introdusă printr-o modificare la apelul de listă
facturi disponibile de la serviciile web apelabile automat prin API.</p></div><p data-index="2">În final, a fost introdusă <b><a data-skip-linkfix="1" href="https://mfinante.gov.ro/web/efactura/transformare-xml-in-pdf">conversia automată din XML în PDF</a>. </b></p><p><b><a data-skip-linkfix="1" href="https://www.digi24.ro/digieconomic/financiar/e-factura-este-obligatorie-de-la-1-ianuarie-2024-din-iulie-dispar-toate-celelalte-tipuri-de-facturi-1505">e-Factura</a></b></p>
a devenit obligatorie de la 1 ianuarie 2024. Nedepunerea ei în sistemul
ANAF nu produce încă efecte, dar ar putea fi sancționată cu <a data-skip-linkfix="1" href="https://www.digi24.ro/digieconomic/financiar/doar-20-dintre-firmele-active-s-au-inregistrat-in-e-factura-care-sunt-amenzile-si-de-cand-incepe-aplicarea-lor-4763">amendă, de la 1 aprilie</a>.
De la 1 iulie, toate facturile dintre firme se vor transmite explusiv
prin acest sistem. În jur de 120.000 de firme au depus până acum
e-Factura, dintr-un total de aproximativ 700.000.</div><div class="page" id="readability-page-1"><p style="text-align: center;">-----</p><p> </p></div></div>
</div>
</div></div></div>
</div>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-46180281071184111422023-11-14T09:35:00.006+02:002023-11-14T15:52:27.619+02:00Server Send Events Stream SSE + Javascript<p><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token" style="color: #a04900;">from</span><span> quart </span><span class="token" style="color: #a04900;">import</span><span> abort</span><span class="token" style="color: #111b27;">,</span><span> make_response</span><span class="token" style="color: #111b27;">,</span><span> request</span><span class="token" style="color: #111b27;">,</span><span> Quart</span></code></p><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span>app </span><span class="token" style="color: #a04900;">=</span><span> Quart</span><span class="token" style="color: #111b27;">(</span><span>__name__</span><span class="token" style="color: #111b27;">)</span><span>
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token decorator annotation" style="color: #111b27;">@app</span><span class="token decorator annotation" style="color: #111b27;">.</span><span class="token decorator annotation" style="color: #111b27;">get</span><span class="token" style="color: #111b27;">(</span><span class="token" style="color: #116b00;">"/sse"</span><span class="token" style="color: #111b27;">)</span><span>
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span></span><span class="token" style="color: #a04900;">async</span><span> </span><span class="token" style="color: #a04900;">def</span><span> </span><span class="token" style="color: #7c00aa;">sse</span><span class="token" style="color: #111b27;">(</span><span class="token" style="color: #111b27;">)</span><span class="token" style="color: #111b27;">:</span><span>
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span> </span><span class="token" style="color: #a04900;">if</span><span> </span><span class="token" style="color: #116b00;">"text/event-stream"</span><span> </span><span class="token" style="color: #a04900;">not</span><span> </span><span class="token" style="color: #a04900;">in</span><span> request</span><span class="token" style="color: #111b27;">.</span><span>accept_mimetypes</span><span class="token" style="color: #111b27;">:</span><span>
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span> abort</span><span class="token" style="color: #111b27;">(</span><span class="token" style="color: #755f00;">400</span><span class="token" style="color: #111b27;">)</span>
</code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span> response </span><span class="token" style="color: #a04900;">=</span><span> </span><span class="token" style="color: #a04900;">await</span><span> make_response</span><span class="token" style="color: #111b27;">(</span><span>
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span> send_events</span><span class="token" style="color: #111b27;">(</span><span class="token" style="color: #111b27;">)</span><span class="token" style="color: #111b27;">,</span><span>
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span> </span><span class="token" style="color: #111b27;">{</span><span>
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span> </span><span class="token" style="color: #116b00;">'Content-Type'</span><span class="token" style="color: #111b27;">:</span><span> </span><span class="token" style="color: #116b00;">'text/event-stream'</span><span class="token" style="color: #111b27;">,</span><span>
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span> </span><span class="token" style="color: #116b00;">'Cache-Control'</span><span class="token" style="color: #111b27;">:</span><span> </span><span class="token" style="color: #116b00;">'no-cache'</span><span class="token" style="color: #111b27;">,</span><span>
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span> </span><span class="token" style="color: #116b00;">'Transfer-Encoding'</span><span class="token" style="color: #111b27;">:</span><span> </span><span class="token" style="color: #116b00;">'chunked'</span><span class="token" style="color: #111b27;">,</span><span>
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span> </span><span class="token" style="color: #111b27;">}</span><span class="token" style="color: #111b27;">,</span><span>
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span> </span><span class="token" style="color: #111b27;">)</span><span>
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span> response</span><span class="token" style="color: #111b27;">.</span><span>timeout </span><span class="token" style="color: #a04900;">=</span><span> </span><span class="token" style="color: #755f00;">None</span><span> </span><span class="token" style="color: #3c526d;"># Disable the timeout for this streaming response</span><span>
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span> </span><span class="token" style="color: #a04900;">return</span><span> response</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span> </span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token" style="color: #006d6d;"><</span><span class="token" style="color: #006d6d;">script</span><span class="token" style="color: #006d6d;">></span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> </span><span class="token script language-javascript dom" style="color: #005a8e;">document</span><span class="token script language-javascript" style="color: #111b27;">.</span><span class="token script language-javascript method" style="color: #7c00aa;">addEventListener</span><span class="token script language-javascript" style="color: #111b27;">(</span><span class="token script language-javascript" style="color: #116b00;">'DOMContentLoaded'</span><span class="token script language-javascript" style="color: #111b27;">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #111b27;">(</span><span class="token script language-javascript" style="color: #005a8e;">event</span><span class="token script language-javascript" style="color: #111b27;">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript arrow" style="color: #a04900;">=></span><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #111b27;">{</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #a04900;">const</span><span class="token script language-javascript"> eventSource </span><span class="token script language-javascript" style="color: #a04900;">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #a04900;">new</span><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #005a8e;">EventSource</span><span class="token script language-javascript" style="color: #111b27;">(</span><span class="token script language-javascript" style="color: #116b00;">'/sse'</span><span class="token script language-javascript" style="color: #111b27;">)</span><span class="token script language-javascript" style="color: #111b27;">;</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> eventSource</span><span class="token script language-javascript" style="color: #111b27;">.</span><span class="token script language-javascript method-variable function-variable method">onmessage</span><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #a04900;">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #a04900;">function</span><span class="token script language-javascript" style="color: #111b27;">(</span><span class="token script language-javascript" style="color: #005a8e;">event</span><span class="token script language-javascript" style="color: #111b27;">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #111b27;">{</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> </span><span class="token script language-javascript console" style="color: #005a8e;">console</span><span class="token script language-javascript" style="color: #111b27;">.</span><span class="token script language-javascript method" style="color: #7c00aa;">log</span><span class="token script language-javascript" style="color: #111b27;">(</span><span class="token script language-javascript" style="color: #116b00;">'New message:'</span><span class="token script language-javascript" style="color: #111b27;">,</span><span class="token script language-javascript"> event</span><span class="token script language-javascript" style="color: #111b27;">.</span><span class="token script language-javascript" style="color: #005a8e;">data</span><span class="token script language-javascript" style="color: #111b27;">)</span><span class="token script language-javascript" style="color: #111b27;">;</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #3c526d;">// You can update the DOM here</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #111b27;">}</span><span class="token script language-javascript" style="color: #111b27;">;</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> eventSource</span><span class="token script language-javascript" style="color: #111b27;">.</span><span class="token script language-javascript method-variable function-variable method">onopen</span><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #a04900;">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #a04900;">function</span><span class="token script language-javascript" style="color: #111b27;">(</span><span class="token script language-javascript" style="color: #005a8e;">event</span><span class="token script language-javascript" style="color: #111b27;">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #111b27;">{</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> </span><span class="token script language-javascript console" style="color: #005a8e;">console</span><span class="token script language-javascript" style="color: #111b27;">.</span><span class="token script language-javascript method" style="color: #7c00aa;">log</span><span class="token script language-javascript" style="color: #111b27;">(</span><span class="token script language-javascript" style="color: #116b00;">'Connection to server opened.'</span><span class="token script language-javascript" style="color: #111b27;">)</span><span class="token script language-javascript" style="color: #111b27;">;</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #111b27;">}</span><span class="token script language-javascript" style="color: #111b27;">;</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> eventSource</span><span class="token script language-javascript" style="color: #111b27;">.</span><span class="token script language-javascript method-variable function-variable method">onerror</span><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #a04900;">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #a04900;">function</span><span class="token script language-javascript" style="color: #111b27;">(</span><span class="token script language-javascript" style="color: #005a8e;">event</span><span class="token script language-javascript" style="color: #111b27;">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #111b27;">{</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> </span><span class="token script language-javascript console" style="color: #005a8e;">console</span><span class="token script language-javascript" style="color: #111b27;">.</span><span class="token script language-javascript method" style="color: #7c00aa;">error</span><span class="token script language-javascript" style="color: #111b27;">(</span><span class="token script language-javascript" style="color: #116b00;">'EventSource failed.'</span><span class="token script language-javascript" style="color: #111b27;">)</span><span class="token script language-javascript" style="color: #111b27;">;</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #111b27;">}</span><span class="token script language-javascript" style="color: #111b27;">;</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #3c526d;">// To close the connection when the window is closed</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> </span><span class="token script language-javascript dom" style="color: #005a8e;">window</span><span class="token script language-javascript" style="color: #111b27;">.</span><span class="token script language-javascript method-variable function-variable method">onbeforeunload</span><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #a04900;">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #111b27;">(</span><span class="token script language-javascript" style="color: #111b27;">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript arrow" style="color: #a04900;">=></span><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #111b27;">{</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> eventSource</span><span class="token script language-javascript" style="color: #111b27;">.</span><span class="token script language-javascript method" style="color: #7c00aa;">close</span><span class="token script language-javascript" style="color: #111b27;">(</span><span class="token script language-javascript" style="color: #111b27;">)</span><span class="token script language-javascript" style="color: #111b27;">;</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #111b27;">}</span><span class="token script language-javascript" style="color: #111b27;">;</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> </span><span class="token script language-javascript" style="color: #111b27;">}</span><span class="token script language-javascript" style="color: #111b27;">)</span><span class="token script language-javascript" style="color: #111b27;">;</span><span class="token script language-javascript">
</span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token script language-javascript"> </span><span class="token" style="color: #006d6d;"></</span><span class="token" style="color: #006d6d;">script</span><span class="token" style="color: #006d6d;">></span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token" style="color: #006d6d;"> </span></code></pre>With parameters: <br /><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token" style="color: #006d6d;">from quart import Quart, request, abort, make_response<br />from dataclasses import dataclass<br /><br />app = Quart(__name__)<br /><br />@dataclass<br />class ServerSentEvent:<br /> data: str<br /> event: str | None = None<br /> id: int | None = None<br /> retry: int | None = None<br /><br /> def encode(self) -> bytes:<br /> message = f"data: {self.data}"<br /> if self.event is not None:<br /> message = f"{message}\nevent: {self.event}"<br /> if self.id is not None:<br /> message = f"{message}\nid: {self.id}"<br /> if self.retry is not None:<br /> message = f"{message}\nretry: {self.retry}"<br /> message = f"{message}\n\n"<br /> return message.encode('utf-8')<br /><br />@app.get("/chat-updates")<br />async def chat_updates():<br /> if "text/event-stream" not in request.accept_mimetypes:<br /> abort(400)<br /><br /> friends = request.args.get('friends', default='false') == 'true'<br /> format = request.args.get('format', default='simple')<br /><br /> async def send_events():<br /> while True:<br /> # Your logic to get updates, possibly filtering based on the query parameters<br /> data = ... # Replace with your data retrieval logic<br /> event = ServerSentEvent(data)<br /> yield event.encode()<br /><br /> response = await make_response(<br /> send_events(),<br /> {<br /> 'Content-Type': 'text/event-stream',<br /> 'Cache-Control': 'no-cache',<br /> 'Transfer-Encoding': 'chunked',<br /> },<br /> )<br /> response.timeout = None<br /> return response<br /><br /># Run the app<br />if __name__ == "__main__":<br /> app.run()</span></code></pre><pre>Javascript:<code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span style="color: #006d6d;"></span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token" style="color: #006d6d;"><</span><span class="token" style="color: #006d6d;">script</span><span class="token" style="color: #006d6d;">></span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token" style="color: #006d6d;">const params = new URLSearchParams({<br /> friends: 'true',<br /> format: 'detailed'<br />});<br /><br />const url = `https://my-server/chat-updates?${params}`;<br />const eventSource = new EventSource(url);<br /><br />eventSource.onmessage = function(event) {<br /> // Handle incoming messages<br /> console.log(event.data);<br />};<br /><br />eventSource.onerror = function(error) {<br /> // Handle any errors that occur<br /> console.error("EventSource failed:", error);<br />}; </span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token" style="color: #006d6d;"></</span><span class="token" style="color: #006d6d;">script</span><span class="token" style="color: #006d6d;">></span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token" style="color: #006d6d;"> </span></code></pre><pre><span class="nu mb ew nr b bf nv nw l nx ny" data-selectable-paragraph="" id="7590"><span class="hljs-comment">// server.js</span><br /><span class="hljs-keyword">const</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http'</span>);<br /><span class="hljs-keyword">const</span> es = <span class="hljs-built_in">require</span>(<span class="hljs-string">'event-stream'</span>);<br /><span class="hljs-comment">// Create a HTTP server</span><br /><span class="hljs-keyword">const</span> server = http.<span class="hljs-title.function">createServer</span>(<span class="hljs-function">(<span class="hljs-params">req, res</span>) =></span> {<br /> <span class="hljs-comment">// Check if the request path is /stream</span><br /> <span class="hljs-keyword">if</span> (req.<span class="hljs-property">url</span> === <span class="hljs-string">'/stream'</span>) {<br /> <span class="hljs-comment">// Set the response headers</span><br /> res.<span class="hljs-title.function">writeHead</span>(<span class="hljs-number">200</span>, {<br /> <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/event-stream'</span>,<br /> <span class="hljs-string">'Cache-Control'</span>: <span class="hljs-string">'no-cache'</span>,<br /> <span class="hljs-string">'Connection'</span>: <span class="hljs-string">'keep-alive'</span><br /> });<br /> <span class="hljs-comment">// Create a counter variable</span><br /> <span class="hljs-keyword">let</span> counter = <span class="hljs-number">0</span>;<br /> <span class="hljs-comment">// Create an interval function that sends an event every second</span><br /> <span class="hljs-keyword">const</span> interval = <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =></span> {<br /> <span class="hljs-comment">// Increment the counter</span><br /> counter++;<br /> <span class="hljs-comment">// Create an event object with name, data, and id properties</span><br /> <span class="hljs-keyword">const</span> event = {<br /> <span class="hljs-attr">name</span>: <span class="hljs-string">'message'</span>,<br /> <span class="hljs-attr">data</span>: <span class="hljs-string">`Hello, this is message number <span class="hljs-subst">${counter}</span>`</span>,<br /> <span class="hljs-attr">id</span>: counter<br /> };<br /> <span class="hljs-comment">// Convert the event object to a string</span><br /> <span class="hljs-keyword">const</span> eventString = <span class="hljs-string">`event: <span class="hljs-subst">${event.name}</span>\ndata: <span class="hljs-subst">${event.data}</span>\nid: <span class="hljs-subst">${event.id}</span>\n\n`</span>;<br /> <span class="hljs-comment">// Write the event string to the response stream</span><br /> res.<span class="hljs-title.function">write</span>(eventString);<br /> <span class="hljs-comment">// End the response stream after 10 events</span><br /> <span class="hljs-keyword">if</span> (counter === <span class="hljs-number">10</span>) {<br /> <span class="hljs-built_in">clearInterval</span>(interval);<br /> res.<span class="hljs-title.function">end</span>();<br /> }<br /> }, <span class="hljs-number">1000</span>);<br /> } <span class="hljs-keyword">else</span> {<br /> <span class="hljs-comment">// Handle other requests</span><br /> res.<span class="hljs-title.function">writeHead</span>(<span class="hljs-number">404</span>);<br /> res.<span class="hljs-title.function">end</span>(<span class="hljs-string">'Not found'</span>);<br /> }<br />});<br /><span class="hljs-comment">// Listen on port 3000</span><br />server.<span class="hljs-title.function">listen</span>(<span class="hljs-number">3000</span>, <span class="hljs-function">() =></span> {<br /> <span class="hljs-variable.language">console</span>.<span class="hljs-title.function">log</span>(<span class="hljs-string">'Server listening on port 3000'</span>);<br />});</span></pre><pre><span class="nu mb ew nr b bf nv nw l nx ny" data-selectable-paragraph="" id="7590"> </span></pre><pre><span class="nu mb ew nr b bf nv nw l nx ny" data-selectable-paragraph="" id="ae83"><span class="hljs-comment">// client.js</span><br /><span class="hljs-comment">// Fetch the event stream from the server</span><br /><span class="hljs-title.function">fetch</span>(<span class="hljs-string">'/stream'</span>)<br /> .<span class="hljs-title.function">then</span>(<span class="hljs-function"><span class="hljs-params">response</span> =></span> {<br /> <span class="hljs-comment">// Get the readable stream from the response body</span><br /> <span class="hljs-keyword">const</span> stream = response.<span class="hljs-property">body</span>;<br /> <span class="hljs-comment">// Get the reader from the stream</span><br /> <span class="hljs-keyword">const</span> reader = stream.<span class="hljs-title.function">getReader</span>();<br /> <span class="hljs-comment">// Define a function to read each chunk</span><br /> <span class="hljs-keyword">const</span> <span class="hljs-title.function">readChunk</span> = () => {<br /> <span class="hljs-comment">// Read a chunk from the reader</span><br /> reader.<span class="hljs-title.function">read</span>()<br /> .<span class="hljs-title.function">then</span>(<span class="hljs-function">(<span class="hljs-params">{<br /> value,<br /> done<br /> }</span>) =></span> {<br /> <span class="hljs-comment">// Check if the stream is done</span><br /> <span class="hljs-keyword">if</span> (done) {<br /> <span class="hljs-comment">// Log a message</span><br /> <span class="hljs-variable.language">console</span>.<span class="hljs-title.function">log</span>(<span class="hljs-string">'Stream finished'</span>);<br /> <span class="hljs-comment">// Return from the function</span><br /> <span class="hljs-keyword">return</span>;<br /> }<br /> <span class="hljs-comment">// Convert the chunk value to a string</span><br /> <span class="hljs-keyword">const</span> chunkString = <span class="hljs-keyword">new</span> <span class="hljs-title.class">TextDecoder</span>().<span class="hljs-title.function">decode</span>(value);<br /> <span class="hljs-comment">// Log the chunk string</span><br /> <span class="hljs-variable.language">console</span>.<span class="hljs-title.function">log</span>(chunkString);<br /> <span class="hljs-comment">// Read the next chunk</span><br /> <span class="hljs-title.function">readChunk</span>();<br /> })<br /> .<span class="hljs-title.function">catch</span>(<span class="hljs-function"><span class="hljs-params">error</span> =></span> {<br /> <span class="hljs-comment">// Log the error</span><br /> <span class="hljs-variable.language">console</span>.<span class="hljs-title.function">error</span>(error);<br /> });<br /> };<br /> <span class="hljs-comment">// Start reading the first chunk</span><br /> <span class="hljs-title.function">readChunk</span>();<br /> })<br /> .<span class="hljs-title.function">catch</span>(<span class="hljs-function"><span class="hljs-params">error</span> =></span> {<br /> <span class="hljs-comment">// Log the error</span><br /> <span class="hljs-variable.language">console</span>.<span class="hljs-title.function">error</span>(error);<br /> });</span><span class="nu mb ew nr b bf nv nw l nx ny" data-selectable-paragraph="" id="7590"> </span><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token" style="color: #006d6d;"> </span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token" style="color: #006d6d;"> </span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token" style="color: #006d6d;">from flask import Flask, Response, render_template<br />import itertools<br />import time<br /><br />app = Flask(__name__)<br /><br />@app.route('/')<br />def index():<br /> return render_template('index.html')<br /><br />@app.route('/connect')<br />def publish_hello():<br /> def stream():<br /> for idx in itertools.count():<br /> msg = f"data: <p>This is {idx}.</p>\n\n"<br /> yield msg<br /> time.sleep(1)<br /> return Response(stream(), mimetype="text/event-stream")<br /></span></code></pre><p style="text-align: left;">Htmx</p><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token" style="color: #006d6d;"><!DOCTYPE html><br /><html><br /><head><br /> <script src="https://unpkg.com/htmx.org@1.8.6"></script><br /> <script src="https://unpkg.com/htmx.org/dist/ext/sse.js"></script><br /></head><br /><body><br /> <div hx-ext="sse" sse-connect="/connect" sse-swap="message"><br /> Contents of this box will be updated in real time with every SSE message received from the server.<br /> </div><br /></body><br /></html><br /> </span></code></pre><pre><span face="-apple-system, Aptos, Roboto, SegoeUI, "Segoe UI", "Helvetica Neue", Helvetica, "Microsoft YaHei", "Meiryo UI", Meiryo, "Arial Unicode MS", sans-serif" style="-webkit-text-stroke-width: 0px; background-color: rgba(255, 255, 255, 0.7); color: #111111; display: inline; float: none; font-size: 16px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-decoration-thickness: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">In this example, the Flask app sends a message to the HTMX client every second. The message is wrapped in an HTML paragraph tag and sent as an SSE event.<span> </span></span><a class="tooltip-target" data-citationid="7fe69c87-fada-fa73-37b6-0efb5d861a19-83-group" href="https://mathspp.com/blog/streaming-data-from-flask-to-htmx-using-server-side-events" style="-webkit-text-stroke-width: 0px; background: var(--cib-color-fill-accent-alt-secondary); border-bottom: 2px solid transparent; border-radius: var(--cib-border-radius-small); color: var(--cib-color-foreground-accent-secondary); cursor: pointer; font-family: -apple-system, Aptos, Roboto, SegoeUI, "Segoe UI", "Helvetica Neue", Helvetica, "Microsoft YaHei", "Meiryo UI", Meiryo, "Arial Unicode MS", sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; position: relative; text-align: start; text-decoration-color: var(--cib-color-foreground-accent-secondary); text-decoration-line: underline; text-decoration-style: dotted; text-indent: 0px; text-transform: none; text-underline-offset: 3px; white-space: normal; widows: 2; word-spacing: 0px;" target="_blank">The HTMX client listens to the SSE endpoint and updates the contents of the HTML element with the<span> </span><code style="background: var(--cib-color-syntax-background-surface); border-radius: var(--cib-border-radius-medium); border: 1px solid var(--cib-color-stroke-neutral-primary); box-sizing: border-box; font-size: var(--cib-type-body1-font-size); font-variation-settings: var(--cib-type-body1-font-variation-settings); font-weight: 500; line-height: var(--cib-type-body1-line-height); margin: 0px 2px; padding: 1px 4px; white-space: pre-wrap;">sse-swap</code><span> </span>attribute with the message received from the server</a>.</pre><pre><a href="https://mathspp.com/blog/streaming-data-from-flask-to-htmx-using-server-side-events">Streaming data from Flask to HTMX using Server-Side Events (SSE) | mathspp</a><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token" style="color: #006d6d;"> </span></code></pre><pre><code style="font-family: var(--font-mono); font-size: 0.8rem; white-space: pre;"><span class="token" style="color: #006d6d;"> </span></code><span class="oe mr fl oa b hl of og l ic oh" data-selectable-paragraph="" id="3fc6">// Client-side Javascript in the HTML</span><span class="oe mr fl oa b hl oi og l ic oh" data-selectable-paragraph="" id="2ca6"> </span></pre><pre><span class="oe mr fl oa b hl oi og l ic oh" data-selectable-paragraph="" id="2ca6">var targetContainer = document.getElementById("this-div");<br />var eventSource = new EventSource("/stream");</span></pre><pre><span class="oe mr fl oa b hl oi og l ic oh" data-selectable-paragraph="" id="c976">eventSource.onmessage = function(e) {<br /> targetContainer.innerHTML = e.data;<br />};</span></pre><pre><span class="oe mr fl oa b hl oi og l ic oh" data-selectable-paragraph="" id="c976"></span></pre><p class="pw-post-body-paragraph ls lt fl lu b lv no lx ly lz np mb mc md nq mf mg mh nr mj mk ml ns mn mo mp eo bj" data-selectable-paragraph="" id="af3a">Generator + SSE: So
why are Python generators good with SSE? It’s simply because they can
keeping looping and yielding data and handing it to the client very
seamlessly. Here is a simple Python implementation of SSE in <a class="af oj" href="http://flask.pocoo.org/" rel="noopener ugc nofollow" target="_blank">Flask</a>:</p><span class="oe mr fl oa b hl of og l ic oh" data-selectable-paragraph="" id="b0ad">@route("/stream")<br />def stream():<br /> def eventStream():<br /> while True:<br /> # Poll data from the database<br /> # and see if there's a new message<br /> if len(messages) > len(previous_messages):<br /> yield "data: <br /> {}\n\n".format(messages[len(messages)-1)])"<br /> <br /> return Response(eventStream(), mimetype="text/event-stream")</span><p class="pw-post-body-paragraph ls lt fl lu b lv lw lx ly lz ma mb mc md me mf mg mh mi mj mk ml mm mn mo mp eo bj" data-selectable-paragraph="" id="5840">This
is a simple hypothetical event source that checks if there’s a new
inbox message and yield the new message. For the browser to acknowledge a
server-sent message, you’ll have to comply to this format:</p><span class="oe mr fl oa b hl of og l ic oh" data-selectable-paragraph="" id="df8b">"data: <any_data>\n\n"</span><p class="pw-post-body-paragraph ls lt fl lu b lv lw lx ly lz ma mb mc md me mf mg mh mi mj mk ml mm mn mo mp eo bj" data-selectable-paragraph="" id="92c0">You have the option to also send with the data the <em class="nt">event</em> and <em class="nt">id</em>.</p><span class="oe mr fl oa b hl of og l ic oh" data-selectable-paragraph="" id="d24b">"id: <any_id>\nevent: <any_message>\ndata: <any_data>\n\n"</span><p class="pw-post-body-paragraph ls lt fl lu b lv lw lx ly lz ma mb mc md me mf mg mh mi mj mk ml mm mn mo mp eo bj" data-selectable-paragraph="" id="b41a">Note that the fields do not have to be in any order as long as there is a newline (<em class="nt">\n</em>) for each field and two (<em class="nt">\n\n</em>) at the end of them. With additional event field, you can have more control how you push data to the browser.</p><span class="oe mr fl oa b hl of og l ic oh" data-selectable-paragraph="" id="c4a7">// Client-side Javascript in the HTML</span><span class="oe mr fl oa b hl oi og l ic oh" data-selectable-paragraph="" id="b1f4">var targetContainer = document.getElementById("this-div");<br />var eventSource = new EventSource("/stream");</span><span class="oe mr fl oa b hl oi og l ic oh" data-selectable-paragraph="" id="4bed">eventSource.addEventListener = (<any_message>, function(e) {<br /> targetContainer.innerHTML = e.data;<br /> <br /> if (e.data > 20) {<br /> targetContainer.style.color = "red";<br /> }<br />};</span><p class="pw-post-body-paragraph ls lt fl lu b lv lw lx ly lz ma mb mc md me mf mg mh mi mj mk ml mm mn mo mp eo bj" data-selectable-paragraph="" id="585d">This
will basically render the DOM with the latest data on the specified
event message and change the color to “red” when it exceeds 20.</p><pre><span class="oe mr fl oa b hl oi og l ic oh" data-selectable-paragraph="" id="c976">https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#receiving_events_from_the_server</span></pre><p>Warning: When not used over HTTP/2,
SSE suffers from a limitation to the maximum number of open connections,
which can be especially painful when opening multiple tabs, as the
limit is per browser and is set to a very low number (6).<br />The issue has been marked as "Won't fix" in <a href="https://crbug.com/275955">Chrome</a> and <a href="https://bugzil.la/906896">Firefox</a>.<br />This limit is per browser + domain, which means that you can open 6 SSE connections<br />across all of the tabs to www.example1.com and another 6 SSE connections to www.example2.com (per <a href="https://stackoverflow.com/questions/5195452/websockets-vs-server-sent-events-eventsource/5326159">Stackoverflow</a>). When using HTTP/2, the maximum number of simultaneous HTTP streams is negotiated between the server and the client (defaults to 100). </p><p>Fields<br />Each message received has some combination of the following fields, one per line:<br /><br />event<br /> A string identifying the type of event described. If this is specified, an event will be dispatched on the browser to the listener for the specified event name; the website source code should use addEventListener() to listen for named events. The onmessage handler is called if no event name is specified for a message.<br /></p><p>data<br /> The data field for the message. When the EventSource receives multiple consecutive lines that begin with data:, it concatenates them, inserting a newline character between each one. Trailing newlines are removed. <br /></p><p>id<br /> The event ID to set the EventSource object's last event ID value. <br /></p><p>retry<br /> The reconnection time. If the connection to the server is lost, the browser will wait for the specified time before attempting to reconnect. This must be an integer, specifying the reconnection time in milliseconds. If a non-integer value is specified, the field is ignored.<br /><br />All other field names are ignored.<br /></p>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-65064844225319889002023-11-05T14:22:00.002+02:002023-11-05T14:39:37.048+02:00Select and Delete Duplicates from Sqlite Table<p><i>Select duplicates from table PonsApimetaDE with columns DE, meta</i><br /><br />SELECT DE, meta, COUNT(*)<br />FROM PonsApimetaDE<br />GROUP BY DE, meta<br />HAVING COUNT(*) > 1<br /><br /><i>Delete duplicates from table PonsApimetaDE with columns DE, meta</i><br /><br />DELETE FROM PonsApimetaDE<br />WHERE rowid NOT IN (<br /> SELECT MIN(rowid)<br /> FROM PonsApimetaDE<br /> GROUP BY DE, meta<br />)<br /></p><p></p><p><i>Delete duplicates from table </i></p>CREATE TABLE temp_table as SELECT DISTINCT * FROM source_table;<br />DELETE FROM source_table;<br />INSERT INTO source_table SELECT * FROM temp_table<br />DROP TABLE temp_table<p><i>Create index for table PonsApimetaDE with columns DE, meta</i><br /><br />CREATE UNIQUE INDEX "idxuniquemetaDE" ON "PonsApimetaDE" (<br /> "DE" ASC,<br /> "meta" ASC<br />)</p><p style="text-align: center;">***** <br /></p>SELECT * FROM table<br />WHERE rowid > (<br /> SELECT MIN(rowid) FROM table p2<br /> WHERE table.column1 = p2.column1<br /> AND table.column2 = p2.column2<br />);<br /><br />DELETE FROM table<br />WHERE rowid > (<br /> SELECT MIN(rowid) FROM table p2<br /> WHERE table.column1 = p2.column1<br /> AND table.column2 = p2.column2<br />);<br /><br />p2 is an alias for the table table in the subquery. This alias is used to make it easier to reference the table table in the subquery without having to type out the entire table name each time.<br /><br />The purpose of this DELETE statement is to delete all rows from the table table where the column1 and column2 are the same as other rows, but only if the current row's rowid is greater than the smallest rowid with the same column1 and column2.<br /><br />Here's a breakdown of the query:<br /><br />The DELETE FROM table statement tells SQLite to delete all rows from the table table that meet the conditions specified in the WHERE clause.<br /><br />The WHERE rowid > (subquery) clause restricts the rows to be deleted based on their rowid.<br /><br />The subquery (SELECT MIN(rowid) FROM table p2 WHERE table.column1 = p2.column1 AND table.column2 = p2.column2) calculates the smallest rowid in the table table that has the same column1 and column2 as the current row.<br /><br />The p2 alias in the subquery allows us to reference the table table without having to type out the entire table name each time.<br /><br />In summary, this query will delete all duplicate rows from the table table, leaving only one row per unique combination of column1 and column2.Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-48389067980707085082023-11-04T21:21:00.003+02:002023-11-05T11:00:03.153+02:00Mongoose Custom Validator String or Number<p></p><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: #569cd6;">const</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">mongoose</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #dcdcaa;">require</span><span style="color: #cccccc;">(</span><span style="color: #ce9178;">'mongoose'</span><span style="color: #cccccc;">);</span></div><div><span style="color: #569cd6;">const</span><span style="color: #cccccc;"> { </span><span style="color: #4ec9b0;">Schema</span><span style="color: #cccccc;"> } </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">mongoose</span><span style="color: #cccccc;">;</span></div><br /><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: #dcdcaa;">main</span><span style="color: #cccccc;">().</span><span style="color: #dcdcaa;">catch</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">err</span><span style="color: #cccccc;"> </span><span style="color: #569cd6;">=></span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">console</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">log</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">err</span><span style="color: #cccccc;">));</span></div><br /><div><span style="color: #569cd6;">async</span><span style="color: #cccccc;"> </span><span style="color: #569cd6;">function</span><span style="color: #cccccc;"> </span><span style="color: #dcdcaa;">main</span><span style="color: #cccccc;">() {</span></div><div><span style="color: #cccccc;"> </span><span style="color: #c586c0;">await</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">mongoose</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">connect</span><span style="color: #cccccc;">(</span><span style="color: #ce9178;">'mongodb://127.0.0.1:27017/test'</span><span style="color: #cccccc;">);</span></div><div><span style="color: #cccccc;"> </span><span style="color: #6a9955;">// use `await mongoose.connect('mongodb://user:password@127.0.0.1:27017/test');`</span></div><div><span style="color: #6a9955;">// if your database has auth enabled</span></div><div><span style="color: #cccccc;">}</span></div></div><div><span style="color: #cccccc;"> </span></div></div><div><span style="color: #569cd6;">const</span><span style="color: #cccccc;"> </span><span style="color: #dcdcaa;">stringornumbervalidator</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #569cd6;">function</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">value</span><span style="color: #cccccc;">) {</span></div><div><span style="color: #cccccc;"> </span><span style="color: #c586c0;">return</span><span style="color: #cccccc;"> </span><span style="color: #569cd6;">typeof</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">value</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">===</span><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'string'</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">||</span><span style="color: #cccccc;"> </span><span style="color: #569cd6;">typeof</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">value</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">===</span><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'number'</span><span style="color: #cccccc;">;</span></div><div><span style="color: #cccccc;">};</span></div><br /><div><span style="color: #569cd6;">const</span><span style="color: #cccccc;"> </span><span style="color: #4fc1ff;">MySchema</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #569cd6;">new</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">Schema</span><span style="color: #cccccc;">({</span></div><div><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">myField</span><span style="color: #9cdcfe;">:</span><span style="color: #cccccc;"> {</span></div><div><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">type</span><span style="color: #9cdcfe;">:</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">Schema</span><span style="color: #cccccc;">.</span><span style="color: #4ec9b0;">Types</span><span style="color: #cccccc;">.</span><span style="color: #4ec9b0;">Mixed</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">validate</span><span style="color: #9cdcfe;">:</span><span style="color: #cccccc;"> {</span></div><div><span style="color: #cccccc;"> </span><span style="color: #dcdcaa;">validator</span><span style="color: #9cdcfe;">:</span><span style="color: #cccccc;"> </span><span style="color: #dcdcaa;">stringornumbervalidator</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">message</span><span style="color: #9cdcfe;">:</span><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'Value should be either a string or a number'</span></div><div><span style="color: #cccccc;"> }</span></div><div><span style="color: #cccccc;"> }</span></div><div><span style="color: #cccccc;">});</span></div><br /><div><span style="color: #569cd6;">const</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">MyModel</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">mongoose</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">model</span><span style="color: #cccccc;">(</span><span style="color: #ce9178;">'MyModel'</span><span style="color: #cccccc;">, </span><span style="color: #4fc1ff;">MySchema</span><span style="color: #cccccc;">);</span></div></div>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-80971362214143416102023-11-04T18:01:00.002+02:002023-11-04T18:01:39.358+02:00Python Asynchronous Context Manager PlayGround<div style="text-align: left;">class AsyncContextManager:<br /> global correlationMap<br /> global requestId<br /> async def __aenter__(self) -> Literal['Waited']: # enter the async context manager<br /> print('>Entering the async context manager') # report a message<br /> await asyncio.sleep(0.05) # block for a moment<br /> return 'Waited'<br /> async def __aexit__(self, exc_type, exc, tb) -> Literal['Exited']: # exit the async context manager<br /> print('>Exiting the async context manager') # send a message<br /> await asyncio.sleep(0.05) # block for a moment<br /> return 'Exited'<br /> async def getresult(self):<br /> await asyncio.sleep(0.05)<br /> # print('Running inside the context manager')<br /> return correlationMap[requestId]<br /> async def dummyasync() -> Literal['Dummy function']:<br /> print(f"Dummy function started")<br /> await asyncio.sleep(0.1)<br /> return 'Dummy function' </div><div style="text-align: left;"> </div><div style="text-align: left;">async with AsyncContextManager():</div><div style="text-align: left;"><span> </span>app.add_background_task(callback)<br /> app.add_background_task(checkResult)</div><div style="text-align: left;"><span> </span>while responsefirstcall.text == 'Waiting...':<br /><span> </span><span> </span>correlationMap[requestId] = await AsyncContextManager().getresult()</div><div style="text-align: left;"><span> </span><span> </span>print('correlationMap before loop: ' + str(correlationMap[requestId]))<br /><span> </span><span> </span><span> </span>while correlationMap[requestId] == 'Waiting...':<br /> <span> </span>await asyncio.sleep(0.2)</div><div style="text-align: left;"><span> </span><span> </span><span> </span><span> </span>print('checkResult inside while loop: ' + str(response.text[:-1]))<br /> <span> </span>correlationMap[requestId] = await AsyncContextManager().getresult()<br /> <span> </span> print('Check result inside while loop: ' + str(correlationMap[requestId][:-1]) + ' ' + str(time.strftime("%A %d:%m:%Y %H:%M:%S UTC%z", time.localtime())))</div><div style="text-align: left;">try:<br /> # response: httpx.Response = await client.get(f'http://{externalip}:5000/checkResult')<br /> if correlationMap[requestId] != 'Waiting...':<br /> # if response.text != 'Waiting...': # print('Not Waiting...')<br /> # etransdomain = scripts.etrans.etrans(sourcelang, [targetlang], 'SPD', searchformterm).domain<br /> # rows.append('E-Translate domain: ' + etransdomain)<br /> rows.append('E-Translate')<br /> rows.append(correlationMap[requestId].replace('\n', ''))<br /> # rows.append(response.text.replace('\n', ''))<br /> print(rows)<br /> break<br /> # else:<br /> # continue<br /> except Exception as exc:<br /> print(exc)<br /> await asyncio.sleep(0.1)<br /> rows.append('E-Translate')<br /> rows.append('Error')<br /> break</div><div style="text-align: left;"> </div><div style="text-align: left;">if rows: print("list is not empty")</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><p><strong>Future</strong></p>
<p>Future is simply an abstraction of value that may be not computed yet
and will be available eventually. It's a simple container that only
does one thing - whenever the value is set, fire all registered
callbacks.</p>
<p>If you want to obtain that value, you register a callback via <code>add_done_callback()</code> method.</p>
<p>But unlike in <code>Promise</code>, the actual computation is done externally - and that external code has to call <code>set_result()</code> method to resolve the future.</p>
<p><strong>Coroutine</strong></p>
<p>Coroutine is the object very similar to <code>Generator</code>.</p>
<p>A generator is typically iterated within <code>for</code> loop. It <em>yields</em> values and, starting from <a href="https://www.python.org/dev/peps/pep-0342/" rel="noreferrer">PEP342</a> acceptance, it <em>receives</em> values.</p>
<p>A coroutine is typically iterated within the event loop in depths of <code>asyncio</code> library. A coroutine yields <code>Future</code>
instances. When you are iterating over a coroutine and it yields a
future, you shall wait until this future is resolved. After that you
shall <code>send</code> the value of future into the coroutine, then you receive another future, and so on.</p>
<p>An <code>await</code> expression is practically identical to <code>yield from</code> expression, so by <em>awaiting</em> other coroutine, you stop until that coroutine has all its futures resolved, and get coroutine's return value. The <code>Future</code> is one-tick iterable and its iterator returns actual Future - that roughly means that <code>await future</code> equals <code>yield from future</code> equals <code>yield future</code>.</p>
<p><strong>Task</strong></p>
<p>Task is Future which has been actually started to compute and is attached to event loop. So it's special kind of Future (class <code>Task</code> is derived from class <code>Future</code>), which is associated with some event loop, and it has some coroutine, which serves as <em>Task executor</em>.</p>
<p>Task is usually created by event loop object: you give a coroutine to
the loop, it creates Task object and starts to iterate over that
coroutine in manner described above. Once the coroutine is finished,
Task's Future is resolved by coroutine's return value.</p>
<p>You see, the task is quite similar to JS Promise - it encapsulates background job and its result.</p>
<p><strong>Coroutine Function and Async Function</strong></p>
<p>Coroutine func is a factory of coroutines, like generator function to
generators. Notice the difference between Python's coroutine function
and Javascript's async function - JS async function, when called,
creates a Promise and its internal generator immediately starts being
iterated, while Python's coroutine does nothing, until Task is created
upon it.</p></div>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-89765440120367493852023-11-04T14:35:00.002+02:002023-11-04T14:35:39.270+02:00API Calls In NodeJS Express<p>Create a new route in express called <em>/getAPIResponse</em>. This route will make a REST API call and return the response as JSON.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">app</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/getAPIResponse</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="c1">// API code will be here</span>
<span class="p">})</span>
</code></pre></div></div>
<p>Install request using npm: <code>npm install --save request</code></p>
<p>Once you have the <em>request</em> module installed, create a file called <em>API_helper.js</em>. This will be wrapper for <em>request</em> module to make API calls. In future if you need to use any other module, you simple need to modify the <em>API_helper.js</em> wrapper and not every where inside the application.</p>
<p>Require the <em>request</em> module inside the <em>API_helper.js</em>. We’ll be returning a promise from the helper method, so here is how the <em>API_helper.js</em> looks :</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">request</span><span class="dl">'</span><span class="p">)</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span>
<span class="cm">/*
** This method returns a promise
** which gets resolved or rejected based
** on the result from the API
*/</span>
<span class="na">make_API_call</span> <span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">url</span><span class="p">){</span>
<span class="k">return</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">request</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="p">{</span> <span class="na">json</span><span class="p">:</span> <span class="kc">true</span> <span class="p">},</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">body</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="nx">reject</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
<span class="nx">resolve</span><span class="p">(</span><span class="nx">body</span><span class="p">)</span>
<span class="p">});</span>
<span class="p">})</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>As seen in the above code, the <em>make_API_call</em> method returns a promise which gets resolved or rejected based on API response.</p>
<p>Require the above module in the <em>app.js</em> file.</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// require API_helper.js
const api_helper = require('./API_helper')
</code></pre></div></div>
<p>Make an API call to the REST API <a href="https://jsonplaceholder.typicode.com/todos/1">https://jsonplaceholder.typicode.com/todos/1</a> using <em>api_helper</em> which returns some dummy JSON data.</p>
<p>Here is the <em>app.js</em> file:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">express</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">express</span><span class="dl">'</span><span class="p">)</span>
<span class="kd">const</span> <span class="nx">api_helper</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">./API_helper</span><span class="dl">'</span><span class="p">)</span>
<span class="kd">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">()</span>
<span class="kd">const</span> <span class="nx">port</span> <span class="o">=</span> <span class="mi">3000</span>
<span class="cm">/*
* Route to DEMO the API call to a REST API Endpoint
* REST URL : https://jsonplaceholder.typicode.com/todos/1
*/</span>
<span class="nx">app</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/getAPIResponse</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">api_helper</span><span class="p">.</span><span class="nx">make_API_call</span><span class="p">(</span><span class="dl">'</span><span class="s1">https://jsonplaceholder.typicode.com/todos/1</span><span class="dl">'</span><span class="p">)</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">response</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">json</span><span class="p">(</span><span class="nx">response</span><span class="p">)</span>
<span class="p">})</span>
<span class="p">.</span><span class="k">catch</span><span class="p">(</span><span class="nx">error</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span>
<span class="p">})</span>
<span class="p">})</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="nx">port</span><span class="p">,</span> <span class="p">()</span> <span class="o">=></span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`App listening on port </span><span class="p">${</span><span class="nx">port</span><span class="p">}</span><span class="s2">!`</span><span class="p">))</span>
</code></pre></div></div>
<p><em>api_helper</em> returns a promise which when resolved returns a <em>JSON</em> or returns an error when rejected.</p>
<p>Save the above changes and restart the server. Point your browser to <a href="http://localhost:3000/getAPIResponse">http://localhost:3000/getAPIResponse</a> and will have the API response returned in the browser.</p>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-32180429781808382612023-11-01T17:58:00.001+02:002023-11-01T17:58:10.060+02:00Truthy and Falsy Values in Python<p></p><p>In Python, individual <strong>values </strong>can evaluate to either <code>True</code> or <code>False</code>.
They do not necessarily have to be part of a larger expression to
evaluate to a truth value because they already have one that has been
determined by the rules of the Python language.</p><p>The basic rules are:</p><ul><li>Values that evaluate to <strong><code>False</code> </strong>are considered <code><strong>Falsy</strong></code>. </li><li>Values that evaluate to <strong><code>True</code> </strong>are considered <code><strong>Truthy</strong></code>. </li></ul><p>According to the <a href="https://docs.python.org/3/library/stdtypes.html#truth-value-testing">Python Documentation</a>:</p><blockquote>Any object can be tested for truth value, for use in an <a href="https://docs.python.org/3/reference/compound_stmts.html#if"><code>if</code></a> or <a href="https://docs.python.org/3/reference/compound_stmts.html#while"><code>while</code></a> condition or as operand of the Boolean operations below (and, or, not).</blockquote><h3 id="-boolean-context">Boolean Context</h3><p>When we use a value as part of a larger expression, or as an <code>if</code> or <code>while</code> condition, we are using it in a <strong>boolean context</strong>. </p><p>You can think of a boolean context as a particular "part" of your code that requires a value to be either <code>True</code> or <code>False</code> to make sense. </p><h3 id="-falsy-values">Falsy Values</h3><p><strong>Sequences and Collections:</strong></p><ul><li>Empty lists <code>[]</code></li><li>Empty tuples <code>()</code></li><li>Empty dictionaries <code>{}</code></li><li>Empty sets <code>set()</code></li><li>Empty strings <code>""</code></li><li>Empty ranges <code>range(0)</code></li></ul><p><strong>Numbers</strong></p><ul><li>Zero of any numeric type. </li><li>Integer: <code>0</code></li><li>Float: <code>0.0</code></li><li>Complex: <code>0j</code></li></ul><p><strong>Constants</strong></p><ul><li><code>None</code></li><li><code>False</code></li></ul><p>Falsy values were the reason why there was no output in our initial example when the value of <code>a</code> was zero.</p><h3 id="-truthy-values">Truthy Values</h3><p>According to the <a href="https://docs.python.org/3/library/stdtypes.html#truth-value-testing">Python Documentation</a>:</p><blockquote>By default, an object is considered <strong>true</strong>.</blockquote><p><strong>Truthy values include:</strong></p><ul style="text-align: left;"><li>Non-empty sequences or collections (lists, tuples, strings, dictionaries, sets).</li><li>Numeric values that are not zero.</li><li><code>True</code></li></ul><code></code><h3 id="-the-built-in-bool-function">The Built-in bool() Function</h3><p>You can check if a value is either truthy or falsy with the built-in <code>bool()</code> function. </p><p>According to the <a href="https://docs.python.org/3/library/functions.html#bool">Python Documentation</a>, this function:</p><blockquote>Returns a Boolean value, i.e. one of <code>True</code> or <code>False</code>. <em>x (the argument)</em> is converted using the standard truth testing procedure.</blockquote><div><pre class="language-python" tabindex="0"><code class="language-python"><span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span>
<span class="token boolean">True</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>
<span class="token boolean">False</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token boolean">False</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token boolean">True</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">5</span><span class="token punctuation">)</span>
<span class="token boolean">True</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">(</span><span class="token number">0.0</span><span class="token punctuation">)</span>
<span class="token boolean">False</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">(</span><span class="token boolean">None</span><span class="token punctuation">)</span>
<span class="token boolean">False</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
<span class="token boolean">True</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">(</span><span class="token builtin">range</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token boolean">False</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">(</span><span class="token builtin">set</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token boolean">False</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token boolean">True</span></code></pre><p> </p><h3 id="__bool-__-">__bool __()</h3><p>With the special method <code>__bool__()</code>, you can set a "customized" condition that will determine when an object of your class will evaluate to <code>True</code> or <code>False</code>. </p><p>According to the <a href="https://docs.python.org/3/library/stdtypes.html#truth-value-testing">Python Documentation</a>:</p><blockquote>By default, an object is considered true unless its class defines either a <a href="https://docs.python.org/3/reference/datamodel.html#object.__bool__"><code>__bool__()</code></a> method that returns <code>False</code> or a <a href="https://docs.python.org/3/reference/datamodel.html#object.__len__"><code>__len__()</code></a> method that returns zero, when called with the object.</blockquote><p>For example, if we have this very simple class:</p><pre class="language-python" tabindex="0"><code class="language-python"><span class="token operator">>></span><span class="token operator">></span> <span class="token keyword">class</span> <span class="token class-name">Account</span><span class="token punctuation">:</span>
<span class="token keyword">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> balance<span class="token punctuation">)</span><span class="token punctuation">:</span>
self<span class="token punctuation">.</span>balance <span class="token operator">=</span> balance</code></pre><p>You can see that no special methods are defined, so all the objects that you create from this class will always evaluate to <code>True</code>:</p><pre class="language-python" tabindex="0"><code class="language-python"><span class="token operator">>></span><span class="token operator">></span> account1 <span class="token operator">=</span> Account<span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">(</span>account1<span class="token punctuation">)</span>
<span class="token boolean">True</span>
<span class="token operator">>></span><span class="token operator">></span> account2 <span class="token operator">=</span> Account<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">(</span>account2<span class="token punctuation">)</span>
<span class="token boolean">True</span></code></pre><p>We can customize this behavior by adding the special method <a href="https://docs.python.org/3/reference/datamodel.html#object.__bool__"><code>__bool__()</code></a>:</p><pre class="language-python" tabindex="0"><code class="language-python"><span class="token operator">>></span><span class="token operator">></span> <span class="token keyword">class</span> <span class="token class-name">Account</span><span class="token punctuation">:</span>
<span class="token keyword">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> balance<span class="token punctuation">)</span><span class="token punctuation">:</span>
self<span class="token punctuation">.</span>balance <span class="token operator">=</span> balance
<span class="token keyword">def</span> <span class="token function">__bool__</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
<span class="token keyword">return</span> self<span class="token punctuation">.</span>balance <span class="token operator">></span> <span class="token number">0</span></code></pre><p>Now, if the account balance is greater than zero, the object will evaluate to <code>True</code>. Otherwise, if the account balance is zero, the object will evaluate to <code>False</code>. </p><pre class="language-python" tabindex="0"><code class="language-python"><span class="token operator">>></span><span class="token operator">></span> account1 <span class="token operator">=</span> Account<span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">(</span>account1<span class="token punctuation">)</span>
<span class="token boolean">True</span>
<span class="token operator">>></span><span class="token operator">></span> account2 <span class="token operator">=</span> Account<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">(</span>account2<span class="token punctuation">)</span>
<span class="token boolean">False</span></code></pre><p>💡 <strong>Tip:</strong> If <code><a href="https://docs.python.org/3/reference/datamodel.html#object.__bool__">__bool__()</a></code> is not defined in the class but the <code>__len__()</code> method is, the value returned by this method will determine if the object is truthy or falsy.</p><h2 id="-in-summary">🔹 In Summary </h2><ul><li>Truthy values are values that evaluate to <code>True</code> in a boolean context.</li><li>Falsy values are values that evaluate to <code>False</code> in a boolean context.</li><li>Falsy values include empty sequences (lists, tuples, strings, dictionaries, sets), zero in every numeric type, <code>None</code>, and <code>False</code>.</li><li>Truthy values include non-empty sequences, numbers (except <code>0</code> in every numeric type), and basically every value that is not falsy. </li><li>They can be used to make your code more concise. </li></ul><p>Source: freecodecamp.org</p><p> </p></div>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-53873280872459421742023-10-29T11:47:00.003+02:002023-10-31T08:24:52.030+02:00Word Macro Insert Page X of Y<p>Sub InsertTotalPages()<br />' Inserts total number of pages in the document at cursor<br /> Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, Text:= _<br /> "NUMPAGES ", PreserveFormatting:=True<br />End Sub<br /> </p><p>Sub InsertPageXofY()<br />' Inserts Page {current_page} of {total_doc_pages} at cursor<br /> Selection.TypeText Text:="Page "<br /> Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldPage, Text:="Page ", _<br /> PreserveFormatting:=True<br /> Selection.TypeText Text:=" of "<br /> Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, Text:= _<br /> "NUMPAGES ", PreserveFormatting:=True<br />End Sub<br /><br /></p>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-59300952019269905932023-10-27T17:42:00.001+03:002023-10-27T17:45:16.214+03:00Python PlatitorTvaRest API<p>from datetime import datetime<br />import requests, json<br /><br />headers = {<br /> 'Accept': 'application/json',<br /> 'Accept-Language': 'en-US,en;q=0.7,ro;q=0.3',<br /> 'Connection': 'keep-alive',<br /> 'Referer': 'https://mfinante.gov.ro',<br /> 'Content-Type': 'application/json',<br />}<br />today = datetime.today().strftime('%Y-%m-%d')<br />data = [{'cui': '19467555', 'data': today}]<br />print(data)<br /><br />response = requests.post('https://webservicesp.anaf.ro/PlatitorTvaRest/api/v8/ws/tva', data=json.dumps(data), headers=headers)<br />print(response.json())</p><p style="text-align: center;"> *****</p><p><span style="font-family: courier;">[{'cui': '19467555', 'data': '2023-10-27'}] <br /></span></p><p><span style="font-family: courier;">{<br /> "cod": 200,<br /> "message": "SUCCESS",<br /> "found": [<br /> {<br /> "date_generale": {<br /> "cui": 19467555,<br /> "data": "2023-10-27",<br /> "denumire": "LEON TIBERIU CRISTIAN PERSOANĂ FIZICĂ AUTORIZATĂ",<br /> "adresa": "JUD. BRAŞOV, MUN. SĂCELE, STR. VALEA CERNATULUI, NR.47",<br /> "nrRegCom": "F08/388/2003",<br /> "telefon": "0729947925",<br /> "fax": "",<br /> "codPostal": "505600",<br /> "act": "",<br /> "stare_inregistrare": "RELUARE ACTIVITATE din data 30.04.2013",<br /> "data_inregistrare": "2007-01-01",<br /> "cod_CAEN": "7430",<br /> "iban": "",<br /> "statusRO_e_Factura": false,<br /> "organFiscalCompetent": "Administraţia Judeţeană a Finanţelor Publice Braşov",<br /> "forma_de_proprietate": "",<br /> "forma_organizare": "",<br /> "forma_juridica": ""<br /> },<br /> "inregistrare_scop_Tva": {<br /> "scpTVA": false,<br /> "perioade_TVA": []<br /> },<br /> "inregistrare_RTVAI": {<br /> "dataInceputTvaInc": "",<br /> "dataSfarsitTvaInc": "",<br /> "dataActualizareTvaInc": "",<br /> "dataPublicareTvaInc": "",<br /> "tipActTvaInc": "",<br /> "statusTvaIncasare": false<br /> },<br /> "stare_inactiv": {<br /> "dataInactivare": "",<br /> "dataReactivare": "",<br /> "dataPublicare": "",<br /> "dataRadiere": "",<br /> "statusInactivi": false<br /> },<br /> "inregistrare_SplitTVA": {<br /> "dataInceputSplitTVA": "",<br /> "dataAnulareSplitTVA": "",<br /> "statusSplitTVA": false<br /> },<br /> "adresa_sediu_social": {<br /> "sdenumire_Strada": "Str. Valea Cernatului",<br /> "snumar_Strada": "47",<br /> "sdenumire_Localitate": "Mun. Săcele",<br /> "scod_Localitate": "157",<br /> "sdenumire_Judet": "BRAŞOV",<br /> "scod_Judet": "8",<br /> "scod_JudetAuto": "BV",<br /> "stara": "",<br /> "sdetalii_Adresa": "",<br /> "scod_Postal": "505600"<br /> },<br /> "adresa_domiciliu_fiscal": {<br /> "ddenumire_Strada": "Str. Valea Cernatului",<br /> "dnumar_Strada": "47",<br /> "ddenumire_Localitate": "Mun. Săcele",<br /> "dcod_Localitate": "157",<br /> "ddenumire_Judet": "BRAŞOV",<br /> "dcod_Judet": "8",<br /> "dcod_JudetAuto": "BV",<br /> "dtara": "",<br /> "ddetalii_Adresa": "",<br /> "dcod_Postal": "505600"<br /> }<br /> }<br /> ],<br /> "notFound": []<br />}</span></p><p><b>More complex solution: https://github.com/agilegeeks/pyAnaf/blob/master/pyAnaf/api.py</b><br /></p><p>from __future__ import unicode_literals, print_function<br /><br />import datetime<br />import sys<br /><br />PY_3_OR_HIGHER = sys.version_info >= (3, 0)<br /><br />try:<br /> import urllib.request as urllib_request<br /> import urllib.error as urllib_error<br />except ImportError:<br /> import urllib2 as urllib_request<br /> import urllib2 as urllib_error<br /><br />try:<br /> from cStringIO import StringIO<br />except ImportError:<br /> from io import BytesIO as StringIO<br /><br />try:<br /> import http.client as http_client<br />except ImportError:<br /> import httplib as http_client<br /><br />try:<br /> import json<br />except ImportError:<br /> import simplejson as json<br /><br />from .models import AnafResultEntry<br /><br /><br />class AnafError(Exception):<br /> """<br /> Base Exception thrown by the Anaf object when there is a<br /> general error interacting with the API.<br /> """<br /> pass<br /><br /><br />class AnafHTTPError(Exception):<br /> """<br /> Exception thrown by the Anaf object when there is an<br /> HTTP error interacting with anaf.ro.<br /> """<br /> pass<br /><br /><br />class AnafResponseError(Exception):<br /> """<br /> Exception thrown by the Anaf object when there is an<br /> error the response returned from ANAF.<br /> """<br /> pass<br /><br /><br />class Anaf(object):<br /> WS_ENDPOINTS = {<br /> 'sync': 'https://webservicesp.anaf.ro/PlatitorTvaRest/api/v3/ws/tva',<br /> 'async': 'https://webservicesp.anaf.ro/AsynchWebService/api/v3/ws/tva'<br /> }<br /> LIMIT = 500<br /><br /> def __init__(self):<br /> self.cuis = {}<br /> self.result = None<br /> self.entries = {}<br /><br /> @staticmethod<br /> def _validate_cui(cui):<br /> if not isinstance(cui, int):<br /> raise AnafError('CUI should be integer')<br /><br /> @staticmethod<br /> def _validate_date(date):<br /> if not isinstance(date, datetime.date):<br /> raise AnafError('Date should be of type datetime.date')<br /><br /> @staticmethod<br /> def _prepare_data(data):<br /> if PY_3_OR_HIGHER:<br /> return bytes(data, 'utf-8')<br /> else:<br /> return data<br /><br /> def addEndpoint(self, url, target='sync'):<br /> if target not in ['sync', 'async']:<br /> raise AnafError('Invalid target for endpoint. Must be one of \'sync\' or \'async\'')<br /><br /> self.WS_ENDPOINTS[target] = url;<br /><br /> def setLimit(self, limit):<br /> try:<br /> self.LIMIT = int(limit)<br /> except:<br /> raise AnafError('Limit should be an integer')<br /><br /> def setCUIList(self, cui_list=[], date=None):<br /> if date is None:<br /> date = datetime.date.today()<br /><br /> if len(cui_list) > self.LIMIT:<br /> raise AnafError('Too many CUIs to be queried. Should limit to %d' % self.LIMIT)<br /><br /> self._validate_date(date)<br /> for cui in cui_list:<br /> self._validate_cui(cui)<br /> self.cuis[cui] = date<br /><br /> def addCUI(self, cui, date=None):<br /> if date is None:<br /> date = datetime.date.today()<br /><br /> self._validate_cui(cui)<br /> self._validate_date(date)<br /><br /> self.cuis[cui] = date<br /> if len(self.cuis.items()) > self.LIMIT:<br /> raise AnafError('Too many CUIs to be queried. Should limit to %d' % self.LIMIT)<br /><br /> def Request(self):<br /> # translate cuis entries to ANAF json format<br /> cui_list = []<br /> for entry in self.cuis.items():<br /> cui_list.append(<br /> {<br /> 'cui': entry[0],<br /> 'data': entry[1].isoformat()<br /> }<br /> )<br /><br /> request = urllib_request.Request(self.WS_ENDPOINTS['sync'])<br /> request.add_header('Content-Type', 'application/json')<br /><br /> try:<br /> response = urllib_request.urlopen(request, self._prepare_data(json.dumps(cui_list)))<br /> except urllib_error.HTTPError as e:<br /> raise AnafHTTPError('Error connecting to ANAF. Got a %d HTTP code.' % e.code)<br /><br /> data = response.read()<br /> if isinstance(data, bytes):<br /> data = data.decode('utf-8')<br /> try:<br /> result = json.loads(data)<br /> except:<br /> raise AnafResponseError('Error parsing json response from ANAF.')<br /><br /> if result['cod'] != 200:<br /> raise AnafResponseError('%s' % result['message'])<br /><br /> result = result['found']<br /> self.result = result<br /><br /> for entry in result:<br /> self.entries[entry['cui']] = AnafResultEntry(entry)<br /><br /> def getCUIData(self, cui):<br /> if cui not in self.entries.keys():<br /> return None<br /><br /> return self.entries[cui] <br /></p>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-16418713872188367682023-10-27T17:31:00.006+03:002023-11-04T18:00:06.843+02:00JavaScript Fetch PlatitorTvaRest Api<div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: #569cd6;">const</span><span style="color: #cccccc;"> </span><span style="color: #4fc1ff;">url</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'https://webservicesp.anaf.ro/PlatitorTvaRest/api/v8/ws/tva'</span><span style="color: #cccccc;">;</span></div><br /><div><span style="color: #569cd6;">const</span><span style="color: #cccccc;"> </span><span style="color: #4fc1ff;">headers</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> {</span></div><div><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'Accept'</span><span style="color: #9cdcfe;">:</span><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'application/json'</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'Accept-Language'</span><span style="color: #9cdcfe;">:</span><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'en-US,en;q=0.7,ro;q=0.3'</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'Connection'</span><span style="color: #9cdcfe;">:</span><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'keep-alive'</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'Referer'</span><span style="color: #9cdcfe;">:</span><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'https://mfinante.gov.ro'</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'Content-Type'</span><span style="color: #9cdcfe;">:</span><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'application/json'</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;">};</span></div><div><span style="color: #569cd6;">const</span><span style="color: #cccccc;"> </span><span style="color: #4fc1ff;">today</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #569cd6;">new</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">Date</span><span style="color: #cccccc;">().</span><span style="color: #dcdcaa;">toISOString</span><span style="color: #cccccc;">().</span><span style="color: #dcdcaa;">slice</span><span style="color: #cccccc;">(</span><span style="color: #b5cea8;">0</span><span style="color: #cccccc;">, </span><span style="color: #b5cea8;">10</span><span style="color: #cccccc;">);</span></div><div><span style="color: #569cd6;">const</span><span style="color: #cccccc;"> </span><span style="color: #4fc1ff;">data</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> [{</span><span style="color: #ce9178;">'cui'</span><span style="color: #9cdcfe;">:</span><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'19467555'</span><span style="color: #cccccc;">, </span><span style="color: #ce9178;">'data'</span><span style="color: #9cdcfe;">:</span><span style="color: #cccccc;"> </span><span style="color: #4fc1ff;">today</span><span style="color: #cccccc;">}];</span></div><div><span style="color: #9cdcfe;">console</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">log</span><span style="color: #cccccc;">(</span><span style="color: #4fc1ff;">data</span><span style="color: #cccccc;">)</span></div><br /><div><span style="color: #dcdcaa;">fetch</span><span style="color: #cccccc;">(</span><span style="color: #4fc1ff;">url</span><span style="color: #cccccc;">, {</span></div><div><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">method</span><span style="color: #9cdcfe;">:</span><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'POST'</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">headers</span><span style="color: #9cdcfe;">:</span><span style="color: #cccccc;"> </span><span style="color: #4fc1ff;">headers</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">body</span><span style="color: #9cdcfe;">:</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">JSON</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">stringify</span><span style="color: #cccccc;">(</span><span style="color: #4fc1ff;">data</span><span style="color: #cccccc;">)</span></div><div><span style="color: #cccccc;">})</span></div><div><span style="color: #cccccc;"> .</span><span style="color: #dcdcaa;">then</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">response</span><span style="color: #cccccc;"> </span><span style="color: #569cd6;">=></span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">response</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">json</span><span style="color: #cccccc;">())</span></div><div><span style="color: #cccccc;"> .</span><span style="color: #dcdcaa;">then</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">data</span><span style="color: #cccccc;"> </span><span style="color: #569cd6;">=></span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">console</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">log</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">data</span><span style="color: #cccccc;">))</span></div><div><span style="color: #cccccc;"> .</span><span style="color: #dcdcaa;">catch</span><span style="color: #cccccc;">((</span><span style="color: #9cdcfe;">error</span><span style="color: #cccccc;">) </span><span style="color: #569cd6;">=></span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">console</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">error</span><span style="color: #cccccc;">(</span><span style="color: #ce9178;">'Error:'</span><span style="color: #cccccc;">, </span><span style="color: #9cdcfe;">error</span><span style="color: #cccccc;">));</span></div></div><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><br /></div><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; text-align: center; white-space: pre;">*****<br /></div><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: #cccccc;">[{cui: '19467555', data: '2023-10-27'}]</span></div></div></div><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;">{<br /> "cod": 200,<br /> "message": "SUCCESS",<br /> "found": [<br /> {<br /> "date_generale": {<br /> "cui": 19467555,<br /> "data": "2023-10-27",<br /> "denumire": "LEON TIBERIU CRISTIAN PERSOANĂ FIZICĂ AUTORIZATĂ",<br /> "adresa": "JUD. BRAŞOV, MUN. SĂCELE, STR. VALEA CERNATULUI, NR.47",<br /> "nrRegCom": "F08/388/2003",<br /> "telefon": "0729947926",<br /> "fax": "",<br /> "codPostal": "505600",<br /> "act": "",<br /> "stare_inregistrare": "RELUARE ACTIVITATE din data 30.04.2013",<br /> "data_inregistrare": "2007-01-01",<br /> "cod_CAEN": "7430",<br /> "iban": "",<br /> "statusRO_e_Factura": false,<br /> "organFiscalCompetent": "Administraţia Judeţeană a Finanţelor Publice Braşov",<br /> "forma_de_proprietate": "",<br /> "forma_organizare": "",<br /> "forma_juridica": ""<br /> },<br /> "inregistrare_scop_Tva": {<br /> "scpTVA": false,<br /> "perioade_TVA": []<br /> },<br /> "inregistrare_RTVAI": {<br /> "dataInceputTvaInc": "",<br /> "dataSfarsitTvaInc": "",<br /> "dataActualizareTvaInc": "",<br /> "dataPublicareTvaInc": "",<br /> "tipActTvaInc": "",<br /> "statusTvaIncasare": false<br /> },<br /> "stare_inactiv": {<br /> "dataInactivare": "",<br /> "dataReactivare": "",<br /> "dataPublicare": "",<br /> "dataRadiere": "",<br /> "statusInactivi": false<br /> },<br /> "inregistrare_SplitTVA": {<br /> "dataInceputSplitTVA": "",<br /> "dataAnulareSplitTVA": "",<br /> "statusSplitTVA": false<br /> },<br /> "adresa_sediu_social": {<br /> "sdenumire_Strada": "Str. Valea Cernatului",<br /> "snumar_Strada": "47",<br /> "sdenumire_Localitate": "Mun. Săcele",<br /> "scod_Localitate": "157",<br /> "sdenumire_Judet": "BRAŞOV",<br /> "scod_Judet": "8",<br /> "scod_JudetAuto": "BV",<br /> "stara": "",<br /> "sdetalii_Adresa": "",<br /> "scod_Postal": "505600"<br /> },<br /> "adresa_domiciliu_fiscal": {<br /> "ddenumire_Strada": "Str. Valea Cernatului",<br /> "dnumar_Strada": "47",<br /> "ddenumire_Localitate": "Mun. Săcele",<br /> "dcod_Localitate": "157",<br /> "ddenumire_Judet": "BRAŞOV",<br /> "dcod_Judet": "8",<br /> "dcod_JudetAuto": "BV",<br /> "dtara": "",<br /> "ddetalii_Adresa": "",<br /> "dcod_Postal": "505600"<br /> }<br /> }<br /> ],<br /> "notFound": []<br />}<br /></div>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-60703894819246630032023-10-26T11:48:00.003+03:002023-10-28T09:40:08.570+03:00Python Iterators, Generator, Yield, Coroutines<h4 style="text-align: left;">Python Iterators, Generator, Yield, Coroutines</h4><div style="text-align: left;"><a href="https://realpython.com/introduction-to-python-generators">https://realpython.com/introduction-to-python-generators</a></div><p style="text-align: justify;">The <b>yield </b>statement suspends a function’s execution and sends a value
back to the caller, but retains enough state to enable the function to
resume where it left off. When the function resumes, it continues
execution immediately after the last yield run. This allows its code to
produce a series of values over time, rather than computing them at once
and sending them back like a list. <b>Return</b> sends a specified value back to its caller whereas <b>Yield</b>
can produce a sequence of values. We should use yield when we want to
iterate over a sequence, but don’t want to store the entire sequence in
memory. Yield is used in Python <b>generators</b>. A generator
function is defined just like a normal function, but whenever it needs
to generate a value, it does so with the yield keyword rather than
return. If the body of a def contains yield, the function automatically
becomes a generator function.</p><h3 style="text-align: left;">Iterables</h3>
<p>When you create a list, you can read its items one by one. Reading its items one by one is called iteration:</p>
<pre class="lang-py s-code-block"><code class="hljs language-python">mylist = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> mylist: <span class="hljs-built_in">print</span>(i)
</code></pre>
<p><code>mylist</code> is an <i>iterable</i>. When you use a list comprehension, you create a list, and so an iterable:</p>
<pre class="lang-py s-code-block"><code class="hljs language-python">mylist = [x*x <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">3</span>)]
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> mylist: <span class="hljs-built_in">print</span>(i)
</code></pre>
<p>Everything you can use "<code>for... in...</code>" on is an iterable; <code>lists</code>, <code>strings</code>, files... These iterables can be read at any time and all their values are stored in memory.</p><h2>Generators</h2>
<p>Generators are iterators, a kind of iterable <b>you can only iterate over once</b>. Generators do not store all the values in memory, <b>they generate the values on the fly</b>:</p>
<pre class="lang-py s-code-block"><code class="hljs language-python">mygenerator = (x*x <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">3</span>))
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> mygenerator: <span class="hljs-built_in">print</span>(i)</code></pre><h2>Yield</h2>
<p><code>yield</code> is a keyword that is used like <code>return</code>, except the function will return a generator.</p><p>
</p><pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">create_generator</span>():
<span> </span>mylist = <span class="hljs-built_in">range</span>(<span class="hljs-number">3</span>)
<span class="hljs-keyword"><span> </span>for</span> i <span class="hljs-keyword">in</span> mylist:
<span class="hljs-keyword">yield</span> i*i
mygenerator = create_generator() <span class="hljs-comment"># create a generator</span>
<span class="hljs-built_in">print</span>(mygenerator) <span class="hljs-comment"># mygenerator is an object!</span> <generator <span class="hljs-built_in">object</span> create_generator at <span class="hljs-number">0xb7555c34</span>>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> mygenerator: <span class="hljs-built_in">print</span>(i)</code></pre><p><b>When you call the function, the </b><b>written </b><b>code in the function body does not run.</b> The function only returns the generator object. The first time the <code>for</code> calls the generator object created from your function, it will run the code in your function from the beginning until it hits <code>yield</code>,
then it'll return the first value of the loop. Then, each subsequent
call will run another iteration of the loop in the
function and return the next value. This will continue until the
generator is considered empty, which happens when the function runs
without hitting <code>yield</code>. That can be because the loop has come to an end, an <code>"if/else"</code> statement is no longer satisfied, StopIteration is raised...</p><h2>Understanding the inner mechanisms of iteration</h2>
<p>Iteration is a process implying iterables (implementing the <code>__iter__()</code> method) and iterators (implementing the <code>__next__()</code> method).
Iterables are any objects you can get an iterator from. Iterators are objects that let you iterate on iterables.</p><p><span class="comment-copy">When you call a function that contains a <code>yield</code>
statement anywhere, you get a generator object, but no code runs. Then
each time you extract an object from the generator, Python executes code
in the function until it comes to a <code>yield</code> statement, then pauses and delivers the object. When you extract another object, Python resumes just after the <code>yield</code> and continues until it reaches another <code>yield</code>
(often the same one, but one iteration later). This continues until the
function runs off the end, at which point the generator is deemed
exhausted.</span></p><p>When you see a function with <code>yield</code> statements, apply this easy trick to understand what will happen:</p>
<ol><li>Insert a line <code>result = []</code> at the start of the function.</li><li>Replace each <code>yield expr</code> with <code>result.append(expr)</code>.</li><li>Insert a line <code>return result</code> at the bottom of the function. </li></ol><pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">class</span> countdown_<span class="hljs-title class_">it</span>erator:
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self</span>):
<span class="hljs-comment"># Start at -1 so that we get 0 when we add 1 below.</span>
self.count = -<span class="hljs-number">1</span>
<span class="hljs-comment"># The __iter__ method will be called once by the 'for' loop.</span>
<span class="hljs-comment"># The rest of the magic happens on the object returned by this method.</span>
<span class="hljs-comment"># In this case it is the object itself.</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__iter__</span>(<span class="hljs-params">self</span>):
<span class="hljs-keyword">return</span> self
<span class="hljs-comment"># The next method will be called repeatedly by the 'for' loop</span>
<span class="hljs-comment"># until it raises StopIteration.</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">next</span>(<span class="hljs-params">self</span>):
self.count += <span class="hljs-number">1</span>
<span class="hljs-keyword">if</span> self.count < <span class="hljs-number">4</span>:
<span class="hljs-keyword">return</span> self.count
<span class="hljs-keyword">else</span>:
<span class="hljs-comment"># A StopIteration exception is raised</span>
<span class="hljs-comment"># to signal that the iterator is done.</span>
<span class="hljs-comment"># This is caught implicitly by the 'for' loop.</span>
<span class="hljs-keyword">raise</span> StopIteration
<span class="hljs-keyword">def</span> <span class="hljs-title function_">some_func</span>():
<span class="hljs-keyword">return</span></code><code class="hljs language-python"> countdown_<span class="hljs-title class_">it</span>erator</code><code class="hljs language-python">()
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> some_func():
<span class="hljs-built_in">print</span> i</code></pre><p> he <code>yield</code> keyword is reduced to two simple facts:
</p><ol><li>If the compiler detects the <code>yield</code> keyword <i>anywhere</i> inside a function, that function no longer returns via the <code>return</code> statement. <i><b>Instead</b></i>, it <b>immediately</b> returns a <b>lazy "pending list" object</b> called a generator</li><li>A generator is iterable. What is an <i>iterable</i>? It's anything like a <code>list</code>, <code>set</code>, <code>range</code>, dictionary view, or any other object with a <i>built-in protocol for visiting each element in a certain order</i>.</li></ol>
<p>In a nutshell: Most commonly, <b>a generator is a lazy, incrementally-pending list</b>, and <b><code>yield</code> statements allow you to use function notation to program the list values</b> the generator should incrementally spit out. <b>Furthermore, advanced usage lets you use generators as coroutines (see below).</b></p><p>Let's define a function <code>makeRange</code> that's just like Python's <code>range</code>. Calling <code>makeRange(n)</code> RETURNS A GENERATOR:</p>
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">makeRange</span>(<span class="hljs-params">n</span>):
<span class="hljs-comment"># return 0,1,2,...,n-1</span>
i = <span class="hljs-number">0</span>
<span class="hljs-keyword">while</span> i < n:
<span class="hljs-keyword">yield</span> i
i += <span class="hljs-number">1</span>
<span class="hljs-meta">>>> </span>makeRange(<span class="hljs-number">5</span>)
<generator <span class="hljs-built_in">object</span> makeRange at <span class="hljs-number">0x19e4aa0</span>>
</code></pre>
<p>To force the generator to immediately return its pending values, you can pass it into <code>list()</code> (just like you could any iterable):</p>
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span><span class="hljs-built_in">list</span>(makeRange(<span class="hljs-number">5</span>))
[<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>] </code></pre><p>The above example can be thought of as merely creating a list that you append to and return:</p><p>
</p><pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-comment"># return a list # # return a generator</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">makeRange</span>(<span class="hljs-params">n</span>): <span class="hljs-comment"># def makeRange(n):</span>
<span class="hljs-string">"""return [0,1,2,...,n-1]"""</span> <span class="hljs-comment"># """return 0,1,2,...,n-1"""</span>
TO_RETURN = [] <span class="hljs-comment"># </span>
i = <span class="hljs-number">0</span> <span class="hljs-comment"># i = 0</span>
<span class="hljs-keyword">while</span> i < n: <span class="hljs-comment"># while i < n:</span>
TO_RETURN += [i] <span class="hljs-comment"># yield i</span>
i += <span class="hljs-number">1</span> <span class="hljs-comment"># i += 1</span>
<span class="hljs-keyword">return</span> TO_RETURN <span class="hljs-comment"># </span>
<span class="hljs-meta">>>> </span>makeRange(<span class="hljs-number">5</span>)
[<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>]</code></pre><p>This is how the "Python iteration protocol" works. That is, what is going on when you do <code>list(makeRange(5))</code>. This is described earlier as a "lazy, incremental list".</p>
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span>x=<span class="hljs-built_in">iter</span>(<span class="hljs-built_in">range</span>(<span class="hljs-number">5</span>))
<span class="hljs-meta">>>> </span><span class="hljs-built_in">next</span>(x) <span class="hljs-comment"># calls x.__next__(); x.next() is deprecated</span>
<span class="hljs-number">0</span>
<span class="hljs-meta">>>> </span><span class="hljs-built_in">next</span>(x)
<span class="hljs-number">1</span>
<span class="hljs-meta">>>> </span><span class="hljs-built_in">next</span>(x)
<span class="hljs-number">2</span>
<span class="hljs-meta">>>> </span><span class="hljs-built_in">next</span>(x)
<span class="hljs-number">3</span>
<span class="hljs-meta">>>> </span><span class="hljs-built_in">next</span>(x)
<span class="hljs-number">4</span>
<span class="hljs-meta">>>> </span><span class="hljs-built_in">next</span>(x)
Traceback (most recent call last):
File <span class="hljs-string">"<stdin>"</span>, line <span class="hljs-number">1</span>, <span class="hljs-keyword">in</span> <module>
StopIteration </code></pre><p>A coroutine (generators that generally accept input via the <code>yield</code> keyword e.g. <code>nextInput = yield nextOutput</code>,
as a form of two-way communication) is basically a computation that is
allowed to pause itself and request input (e.g. to what it should do
next). When the coroutine pauses itself (when the running coroutine
eventually hits a <code>yield</code> keyword), the computation is paused
and control is inverted (yielded) back to the 'calling' function (the
frame which requested the <code>next</code> value of the computation).
The paused generator/coroutine remains paused until another invoking
function (possibly a different function/context) requests the next value
to unpause it (usually passing input data to direct the paused logic
interior to the coroutine's code). One can think of Python coroutines as lazy
incrementally-pending lists, where the next element doesn't just depend
on the previous computation but also on input that you may opt to inject
during the generation process.</p><p><code class="hljs language-python">x = myRange(<span class="hljs-number">5</span>)</code></p><pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-built_in">list</span>(x) #[<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>]
<span class="hljs-built_in">list</span>(x) # []
</code></pre>
<p>A generator is an <i>iterator</i>; that is, it is one-time-use. If you want to reuse it, you should call <code>myRange(...)</code> again. If you need to use the result twice, convert the result to a list and store it in a variable <code>x = list(myRange(5))</code>.</p><ul><li>A function with <a href="https://docs.python.org/reference/expressions.html#yieldexpr" rel="noreferrer"><b><code>yield</code></b></a>, when called, <b>returns a <a href="https://docs.python.org/2/tutorial/classes.html#generators" rel="noreferrer">Generator</a>.</b></li><li>Generators are iterators because they implement the <a href="https://docs.python.org/2/library/stdtypes.html#iterator-types" rel="noreferrer"><b>iterator protocol</b></a>, so you can iterate over them.</li><li>A generator can also be <b>sent information</b>, making it conceptually a <b>coroutine</b>.</li><li>In Python 3, you can <b>delegate</b> from one generator to another in both directions with <b><code>yield from</code></b>.</li></ul><p><b><code>yield</code></b> is only legal inside of a function definition, and <b>the inclusion of <code>yield</code> in a function definition makes it return a generator. </b>When the generator is called (methods are discussed below) execution resumes and then freezes at the next yield. The generator type is a sub-type of iterator. An <code>Iterator</code> can't be reused or reset once exhausted. Another generator should be created to use its functionality again. <br /></p><h2 style="text-align: left;">Coroutines:</h2>
<p><code>yield</code> forms an expression that allows data to be sent into the generator. </p>
<p>The <code>received</code> variable will point to the data that is sent to the generator:</p>
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">bank_account</span>(<span class="hljs-params">deposited, interest_rate</span>):
<span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
calculated_interest = interest_rate * deposited
received = <span class="hljs-keyword">yield</span> calculated_interest
<span class="hljs-keyword">if</span> received:
deposited += received
my_account = bank_account(<span class="hljs-number">1000</span>, <span class="hljs-number">.05</span>)</code></pre>
<p>First, we must queue up the generator with the built-in function, <a href="https://docs.python.org/2/library/functions.html#next" rel="noreferrer"><code>next</code></a>. It will
call the appropriate <code>next</code>.</p><div style="text-align: left;">
<code class="hljs language-python">first_year_interest = <span class="hljs-built_in">next</span>(my_account)</code></div><div style="text-align: left;"><code class="hljs language-python">first_year_interest</code></div><div style="text-align: left;"><code class="hljs language-python"><span class="hljs-number">50.0</span>
</code>
</div><p>And now we can send data into the generator. (<a href="https://www.python.org/dev/peps/pep-0342/#specification-sending-values-into-generators" rel="noreferrer">Sending <code>None</code> is
the same as calling <code>next</code></a>.) :</p><div style="text-align: left;">
<code class="hljs language-python">next_year_interest = my_account.send(first_year_interest + <span class="hljs-number">1000</span>)</code></div><div style="text-align: left;"><code class="hljs language-python">next_year_interest</code></div><div style="text-align: left;"><code class="hljs language-python"><span class="hljs-number">102.5</span>
</code></div><p>Cooperative Delegation to Sub-Coroutine with yield from. Other methods: close and throw.<b> </b>In a generator function, the return statement indicates that the generator is done and will cause StopIteration to be raised. The returned value (if any) is used as an argument to construct StopIteration and becomes the StopIteration.value attribute.</p><p>yield is similar to return - it returns whatever you tell it to (as a generator). The difference is that the next time you call the generator, execution starts from the last call to the yield statement. Unlike return, the stack frame is not cleaned up when a yield occurs, however control is transferred back to the caller, so its state will resume the next time the function is called.</p><p>Yield is single-pass: you can only iterate through once. When a function has a yield in it we call it a generator function. And an iterator is what it returns. Those terms are revealing. We lose the convenience of a container, but gain the power of a series that's computed as needed, and arbitrarily long.<br /><br />Yield is lazy, it puts off computation. A function with a yield in it doesn't actually execute at all when you call it. It returns an iterator object that remembers where it left off. Each time you call next() on the iterator (this happens in a for-loop) execution inches forward to the next yield. return raises StopIteration and ends the series (this is the natural end of a for-loop).<br /><br />Yield is versatile. Data doesn't have to be stored all together, it can be made available one at a time. It can be infinite. If you need multiple passes and the series isn't too long, just call list(generator).</p><p>Use send method inside a generator to send data back to the generator. To allow that, a (yield) is used.</p><p><code>iterator</code> is a more general concept: any object whose class has a <code>__next__</code> method (<code>next</code> in Python 2) and an <code>__iter__</code> method that does <code>return self</code>.</p>
<p>Every generator is an iterator, but not vice versa. A generator is built by calling a function that has one or more <code>yield</code> expressions (<code>yield</code> statements, in Python 2.5 and earlier), and is an object that meets the previous paragraph's definition of an <code>iterator</code>.</p>
<p>You may want to use a custom iterator, rather than a generator, when
you need a class with somewhat complex state-maintaining behavior, or
want to expose other methods besides <code>__next__</code> (and <code>__iter__</code> and <code>__init__</code>). Most often, a generator (sometimes, for sufficiently simple needs, a generator <i>expression</i>)
is sufficient, and it's simpler to code because state maintenance
(within reasonable limits) is basically "done for you" by the frame
getting suspended and resumed.</p><pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">squares</span>(<span class="hljs-params">start, stop</span>):
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(start, stop):
<span class="hljs-keyword">yield</span> i * i
generator = squares(a, b)</code></pre><pre class="lang-py s-code-block"><span style="font-family: times;">or the equivalent generator expression (genexp)</span></pre><pre class="lang-py s-code-block"><code class="hljs language-python">generator = (i*i <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(a, b))</code><code class="hljs language-python"> </code></pre><p> would take more code to build as a custom iterator:</p><pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Squares</span>(<span class="hljs-title class_ inherited__">object</span>):
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self, start, stop</span>):
self.start = start
self.stop = stop
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__iter__</span>(<span class="hljs-params">self</span>):
<span class="hljs-keyword">return</span> self
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__next__</span>(<span class="hljs-params">self</span>): <span class="hljs-comment"># next in Python 2</span>
<span class="hljs-keyword">if</span> self.start >= self.stop:
<span class="hljs-keyword">raise</span> StopIteration
current = self.start * self.start
self.start += <span class="hljs-number">1</span>
<span class="hljs-keyword">return</span> current
iterator = Squares(a, b)</code></pre><pre class="lang-py s-code-block"><span style="font-family: times;">But, of course, with class <code>Squares</code> you could easily offer extra methods, i.e.</span></pre><pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">current</span>(<span class="hljs-params">self</span>):
<span class="hljs-keyword">return</span> self.start</code><code class="hljs language-python"> </code></pre><p>W<span class="comment-copy">hen type hinting a generator that only yields values can be annotated as an <a href="https://docs.python.org/3/library/typing.html#typing.Generator" rel="nofollow noreferrer">Iterator more simply</a> (<code>Generator[int, None, None]</code> === <code>Iterator[int]</code>)</span>
</p><div class="d-inline-flex ai-center"> When a generator function is called, it returns an generator object
without even beginning the execution of the function. When the <code>next()</code> method is called for the first time, the function starts executing until it reaches a <code>yield</code> statement which returns the yielded value. The <code>yield</code> keeps track of what has happened, i.e. it remembers the last execution. And secondly, the <code>next()</code> call continues from the previous value. <i><b>Generator functions</b></i> are ordinary functions defined using <code>yield</code> instead of <code>return</code>. When called, a generator function returns a <i><b>generator object</b></i>, which is a kind of iterator - it has a <code>next()</code> method. When you call <code>next()</code>, the next value yielded by the generator function is returned.</div><div class="d-inline-flex ai-center"><pre class="lang-py s-code-block"><code class="hljs language-python" style="font-family: times;">A generator function <span class="hljs-keyword">is</span> a function <span class="hljs-keyword">with</span> <span class="hljs-keyword">yield</span> <span class="hljs-keyword">in</span> it.
A generator expression <span class="hljs-keyword">is</span> like a <span class="hljs-built_in">list</span> comprehension. It uses <span class="hljs-string">"()"</span> vs <span class="hljs-string">"[]"</span>
A generator <span class="hljs-built_in">object</span> (often called <span class="hljs-string">'a generator'</span>) <span class="hljs-keyword">is</span> returned by both above.
A generator <span class="hljs-keyword">is</span> also a subtype of iterator.</code></pre><pre class="lang-py s-code-block"><span style="font-family: times;">A generator has a <code>close</code> method, while typical iterators don’t. The <code>close</code> method triggers a <code>StopIteration</code> exception in the generator,</span></pre><pre class="lang-py s-code-block"><span style="font-family: times;">which may be caught in a <code>finally </code> clause in that iterator, to get a chance to run some clean‑up.</span></pre><pre class="lang-py s-code-block"><span style="font-family: times;">This abstraction makes it most usable in the large than simple iterators.</span></pre><pre class="lang-py s-code-block"><span style="font-family: times;">One can close a generator as one could close a file, without having to bother about what’s underneath.</span></pre><pre class="lang-py s-code-block"><span style="font-family: times;">Besides, if you check the memory footprint, the generator takes much less memory,</span></pre><pre class="lang-py s-code-block"><span style="font-family: times;">as it doesn't need to store all the values in memory at the same time. </span></pre><pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">myGeneratorList</span>(<span class="hljs-params">n</span>):
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):
<span class="hljs-keyword">yield</span> i
<span class="hljs-keyword">def</span> <span class="hljs-title function_">myIterableList</span>(<span class="hljs-params">n</span>):
ll = n*[<span class="hljs-literal">None</span>]
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):
ll[i] = i
<span class="hljs-keyword">return</span> ll
<span class="hljs-comment"># Same values</span>
ll1 = myGeneratorList(<span class="hljs-number">10</span>)
ll2 = myIterableList(<span class="hljs-number">10</span>)
<span class="hljs-keyword">for</span> i1, i2 <span class="hljs-keyword">in</span> <span class="hljs-built_in">zip</span>(ll1, ll2):
<span class="hljs-built_in">print</span>(<span class="hljs-string">"{} {}"</span>.<span class="hljs-built_in">format</span>(i1, i2))
<span class="hljs-comment"># Generator can only be read once</span>
ll1 = myGeneratorList(<span class="hljs-number">10</span>)
ll2 = myIterableList(<span class="hljs-number">10</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">"{} {}"</span>.<span class="hljs-built_in">format</span>(<span class="hljs-built_in">len</span>(<span class="hljs-built_in">list</span>(ll1)), <span class="hljs-built_in">len</span>(ll2)))
<span class="hljs-built_in">print</span>(<span class="hljs-string">"{} {}"</span>.<span class="hljs-built_in">format</span>(<span class="hljs-built_in">len</span>(<span class="hljs-built_in">list</span>(ll1)), <span class="hljs-built_in">len</span>(ll2)))
<span class="hljs-comment"># Generator can be read several times if converted into iterable</span>
ll1 = <span class="hljs-built_in">list</span>(myGeneratorList(<span class="hljs-number">10</span>))
ll2 = myIterableList(<span class="hljs-number">10</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">"{} {}"</span>.<span class="hljs-built_in">format</span>(<span class="hljs-built_in">len</span>(<span class="hljs-built_in">list</span>(ll1)), <span class="hljs-built_in">len</span>(ll2)))
<span class="hljs-built_in">print</span>(<span class="hljs-string">"{} {}"</span>.<span class="hljs-built_in">format</span>(<span class="hljs-built_in">len</span>(<span class="hljs-built_in">list</span>(ll1)), <span class="hljs-built_in">len</span>(ll2)))</code></pre><p>An <b>iterable object</b> is something which can be iterated (naturally). To do that, however, you will need something like an <b>iterator object</b>, and, yes, the terminology may be confusing. Iterable objects include a <code>__iter__</code> method which will return the iterator object for the iterable object.</p>
<p>An iterator object is an object which implements the <b>iterator protocol</b> - a set of rules. In this case, it must have at least these two methods: <code>__iter__</code> and <code>__next__</code>. The <code>__next__</code> method is a function which supplies a new value. The <code>__iter__</code> method returns the iterator object. In a more complex object, there may be a separate iterator, but in a simpler case, <code>__iter__</code> returns the object itself (typically <code>return self</code>).</p>
<p>One iterable object is a <code>list</code> object. It’s not an iterator, but it has an <code>__iter__</code> method which returns an iterator. You can call this method directly as <code>things.__iter__()</code>, or use <code>iter(things)</code>.</p><p>Writing an iterator yourself can be tedious, so Python has a simpler alternative: the <b>generator function</b>.
A generator function is not an ordinary function. Instead of running
through the code and returning a final result, the code is deferred, and
the function returns immediately with a <b>generator object</b>. A generator object is like an iterator object in that it implements
the iterator protocol. All generators are iterators but not vice versa.</p><p> </p><pre class="lang-py s-code-block"></pre></div><p></p>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-14154900179911617542023-10-21T19:51:00.007+03:002023-10-31T18:45:09.811+02:00Useful Python String Methods<div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: #c586c0;">import</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">string</span></div><div><span style="color: #9cdcfe;">ascii_letters</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">list</span><span style="color: #cccccc;">(</span><span style="color: #4ec9b0;">string</span><span style="color: #cccccc;">.</span><span style="color: #9cdcfe;">ascii_letters</span><span style="color: #cccccc;">)</span></div><div><span style="color: #dcdcaa;">print</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">ascii_letters</span><span style="color: #cccccc;">)</span></div><div><span style="color: #9cdcfe;">ascii_lowercase</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">list</span><span style="color: #cccccc;">(</span><span style="color: #4ec9b0;">string</span><span style="color: #cccccc;">.</span><span style="color: #9cdcfe;">ascii_lowercase</span><span style="color: #cccccc;">)</span></div><div><span style="color: #dcdcaa;">print</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">ascii_lowercase</span><span style="color: #cccccc;">)</span></div><div><span style="color: #cccccc;">print(list(chr(x) for x in range(97, 123))) </span><span style="color: #cccccc;"> </span></div><div><span style="color: #9cdcfe;">ascii_uppercase</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">list</span><span style="color: #cccccc;">(</span><span style="color: #4ec9b0;">string</span><span style="color: #cccccc;">.</span><span style="color: #9cdcfe;">ascii_uppercase</span><span style="color: #cccccc;">)</span></div><div><span style="color: #dcdcaa;">print</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">ascii_uppercase</span><span style="color: #cccccc;">)</span></div><div><span style="color: #cccccc;">print(list(chr(x) for x in range(65, 91))) </span></div><div><span style="color: #9cdcfe;">digits</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">list</span><span style="color: #cccccc;">(</span><span style="color: #4ec9b0;">string</span><span style="color: #cccccc;">.</span><span style="color: #9cdcfe;">digits</span><span style="color: #cccccc;">)</span></div><div><span style="color: #dcdcaa;">print</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">digits</span><span style="color: #cccccc;">)</span></div><div><span style="color: #cccccc;">print(list(chr(x) for x in range(48, 58))) </span></div><div><span style="color: #9cdcfe;">punctuation</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">list</span><span style="color: #cccccc;">(</span><span style="color: #4ec9b0;">string</span><span style="color: #cccccc;">.</span><span style="color: #9cdcfe;">punctuation</span><span style="color: #cccccc;">)</span></div><div><span style="color: #dcdcaa;">print</span><span style="color: #cccccc;">(</span><span style="color: #4ec9b0;">string</span><span style="color: #cccccc;">.</span><span style="color: #9cdcfe;">punctuation</span><span style="color: #cccccc;">)</span></div><div><span style="color: #dcdcaa;">print</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">punctuation</span><span style="color: #cccccc;">)</span></div><div><span style="color: #6aa84f;"># <span class="sig-prename descclassname"><span class="pre"></span></span><span class="sig-name descname"><span class="pre">capitalize</span></span><span class="sig-paren"> words</span></span></div><div><span style="color: #dcdcaa;">print</span><span style="color: #cccccc;">(</span><span style="color: #4ec9b0;">string</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">capwords</span><span style="color: #cccccc;">(</span><span style="color: #ce9178;">"</span><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: #ce9178;">ALL words iN sTRing's TransformeD 2to tiTle $CaSe# &caSe% ștuț şanţ ß groß ßa aßen"</span><span style="color: #cccccc;">, </span><span style="color: #9cdcfe;">sep</span><span style="color: #d4d4d4;">=</span><span style="color: #569cd6;">None</span><span style="color: #cccccc;">))</span></div></div></div></div></div></div></div></div></div><br /><div><span style="color: #6a9955;">#Generate all possible pairs of 2 from the lower/upper case alphabet</span></div><div><span style="color: #c586c0;">from</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">itertools</span><span style="color: #cccccc;"> </span><span style="color: #c586c0;">import</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">product</span></div><div><span style="color: #9cdcfe;">alphabet</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">list</span><span style="color: #cccccc;">(</span><span style="color: #4ec9b0;">string</span><span style="color: #cccccc;">.</span><span style="color: #9cdcfe;">ascii_letters</span><span style="color: #cccccc;">)</span></div><div><span style="color: #9cdcfe;">two_letter_words</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">product</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">alphabet</span><span style="color: #cccccc;">, </span><span style="color: #9cdcfe;">alphabet</span><span style="color: #cccccc;">)</span></div><div><span style="color: #c586c0;">for</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">word</span><span style="color: #cccccc;"> </span><span style="color: #dcdcaa;">in</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">two_letter_words</span><span style="color: #cccccc;">:</span></div><div><span style="color: #cccccc;"> </span><span style="color: #dcdcaa;">print</span><span style="color: #cccccc;"> (</span><span style="color: #9cdcfe;">word</span><span style="color: #cccccc;">)</span></div><br /><div><span style="color: #6a9955;"># Same result with repeat</span></div><div><span style="color: #9cdcfe;">two_letter_words</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">product</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">alphabet</span><span style="color: #cccccc;">, </span><span style="color: #9cdcfe;">repeat</span><span style="color: #d4d4d4;">=</span><span style="color: #b5cea8;">2</span><span style="color: #cccccc;">)</span></div><div><span style="color: #cccccc;"> </span></div><div><span style="color: #6a9955;"># print(len(two_letter_words))</span></div><div><span style="color: #6a9955;">#TypeError: object of type 'itertools.product' has no len()</span></div></div><pre class="showoutput" id="log">['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
['!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~']
All Words In String's Transformed 2to Title $case# &case% Ștuț Şanţ Ss Groß Ssa Aßen
('a', 'a')
('a', 'b')
('a', 'c')
('a', 'd')</pre><pre class="showoutput" id="log">...</pre><pre class="showoutput" id="log">('Z', 'X')
('Z', 'Y')
('Z', 'Z')</pre><br />print(list(chr(x) for x in range(32, 48)))<br />[' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/']<br /><br />newlist = [' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/']<br />print(list(ord(x) for x in newlist))[32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47]<br /><div style="text-align: center;"><pre class="showoutput" id="log">*****</pre></div><section id="string-constants">
<h2><span class="highlighted">String</span> constants<a class="headerlink" href="https://docs.python.org/3/library/string.html?highlight=string#string-constants" title="Permalink to this headline"></a></h2>
<p>The constants defined in this module are:</p>
<dl class="py data"><dt class="sig sig-object py" id="string.ascii_letters">
<span class="sig-prename descclassname"><span class="pre"><span class="highlighted">string</span>.</span></span><span class="sig-name descname"><span class="pre">ascii_letters</span></span><a class="headerlink" href="https://docs.python.org/3/library/string.html?highlight=string#string.ascii_letters" title="Permalink to this definition"></a></dt><dd><p>The concatenation of the <a class="reference internal" href="https://docs.python.org/3/library/string.html?highlight=string#string.ascii_lowercase" title="string.ascii_lowercase"><code class="xref py py-const docutils literal notranslate"><span class="pre">ascii_lowercase</span></code></a> and <a class="reference internal" href="https://docs.python.org/3/library/string.html?highlight=string#string.ascii_uppercase" title="string.ascii_uppercase"><code class="xref py py-const docutils literal notranslate"><span class="pre">ascii_uppercase</span></code></a>
constants described below. This value is not locale-dependent.</p>
</dd></dl>
<dl class="py data"><dt class="sig sig-object py" id="string.ascii_lowercase">
<span class="sig-prename descclassname"><span class="pre"><span class="highlighted">string</span>.</span></span><span class="sig-name descname"><span class="pre">ascii_lowercase</span></span><a class="headerlink" href="https://docs.python.org/3/library/string.html?highlight=string#string.ascii_lowercase" title="Permalink to this definition"></a></dt><dd><p>The lowercase letters <code class="docutils literal notranslate"><span class="pre">'abcdefghijklmnopqrstuvwxyz'</span></code>. This value is not
locale-dependent and will not change.</p>
</dd></dl>
<dl class="py data"><dt class="sig sig-object py" id="string.ascii_uppercase">
<span class="sig-prename descclassname"><span class="pre"><span class="highlighted">string</span>.</span></span><span class="sig-name descname"><span class="pre">ascii_uppercase</span></span><a class="headerlink" href="https://docs.python.org/3/library/string.html?highlight=string#string.ascii_uppercase" title="Permalink to this definition"></a></dt><dd><p>The uppercase letters <code class="docutils literal notranslate"><span class="pre">'ABCDEFGHIJKLMNOPQRSTUVWXYZ'</span></code>. This value is not
locale-dependent and will not change.</p>
</dd></dl>
<dl class="py data"><dt class="sig sig-object py" id="string.digits">
<span class="sig-prename descclassname"><span class="pre"><span class="highlighted">string</span>.</span></span><span class="sig-name descname"><span class="pre">digits</span></span><a class="headerlink" href="https://docs.python.org/3/library/string.html?highlight=string#string.digits" title="Permalink to this definition"></a></dt><dd><p>The <span class="highlighted">string</span> <code class="docutils literal notranslate"><span class="pre">'0123456789'</span></code>.</p>
</dd></dl>
<dl class="py data"><dt class="sig sig-object py" id="string.hexdigits">
<span class="sig-prename descclassname"><span class="pre"><span class="highlighted">string</span>.</span></span><span class="sig-name descname"><span class="pre">hexdigits</span></span><a class="headerlink" href="https://docs.python.org/3/library/string.html?highlight=string#string.hexdigits" title="Permalink to this definition"></a></dt><dd><p>The <span class="highlighted">string</span> <code class="docutils literal notranslate"><span class="pre">'0123456789abcdefABCDEF'</span></code>.</p>
</dd></dl>
<dl class="py data"><dt class="sig sig-object py" id="string.octdigits">
<span class="sig-prename descclassname"><span class="pre"><span class="highlighted">string</span>.</span></span><span class="sig-name descname"><span class="pre">octdigits</span></span><a class="headerlink" href="https://docs.python.org/3/library/string.html?highlight=string#string.octdigits" title="Permalink to this definition"></a></dt><dd><p>The <span class="highlighted">string</span> <code class="docutils literal notranslate"><span class="pre">'01234567'</span></code>.</p>
</dd></dl>
<dl class="py data"><dt class="sig sig-object py" id="string.punctuation">
<span class="sig-prename descclassname"><span class="pre"><span class="highlighted">string</span>.</span></span><span class="sig-name descname"><span class="pre">punctuation</span></span><a class="headerlink" href="https://docs.python.org/3/library/string.html?highlight=string#string.punctuation" title="Permalink to this definition"></a></dt><dd><p><span class="highlighted">String</span> of ASCII characters which are considered punctuation characters
in the <code class="docutils literal notranslate"><span class="pre">C</span></code> locale: <code class="docutils literal notranslate"><span class="pre">!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~</span></code>.</p>
</dd></dl>
<dl class="py data"><dt class="sig sig-object py" id="string.printable">
<span class="sig-prename descclassname"><span class="pre"><span class="highlighted">string</span>.</span></span><span class="sig-name descname"><span class="pre">printable</span></span><a class="headerlink" href="https://docs.python.org/3/library/string.html?highlight=string#string.printable" title="Permalink to this definition"></a></dt><dd><p><span class="highlighted">String</span> of ASCII characters which are considered printable. This is a
combination of <a class="reference internal" href="https://docs.python.org/3/library/string.html?highlight=string#string.digits" title="string.digits"><code class="xref py py-const docutils literal notranslate"><span class="pre">digits</span></code></a>, <a class="reference internal" href="https://docs.python.org/3/library/string.html?highlight=string#string.ascii_letters" title="string.ascii_letters"><code class="xref py py-const docutils literal notranslate"><span class="pre">ascii_letters</span></code></a>, <a class="reference internal" href="https://docs.python.org/3/library/string.html?highlight=string#string.punctuation" title="string.punctuation"><code class="xref py py-const docutils literal notranslate"><span class="pre">punctuation</span></code></a>,
and <a class="reference internal" href="https://docs.python.org/3/library/string.html?highlight=string#string.whitespace" title="string.whitespace"><code class="xref py py-const docutils literal notranslate"><span class="pre">whitespace</span></code></a>.</p>
</dd></dl>
<dl class="py data"><dt class="sig sig-object py" id="string.whitespace">
<span class="sig-prename descclassname"><span class="pre"><span class="highlighted">string</span>.</span></span><span class="sig-name descname"><span class="pre">whitespace</span></span><a class="headerlink" href="https://docs.python.org/3/library/string.html?highlight=string#string.whitespace" title="Permalink to this definition"></a></dt><dd><p>A <span class="highlighted">string</span> containing all ASCII characters that are considered whitespace.
This includes the characters space, tab, linefeed, return, formfeed, and
vertical tab.</p><section id="helper-functions" style="text-align: left;">
<h3 style="text-align: left;">Helper functions</h3>
</section><section id="helper-functions" style="text-align: left;"><span class="sig-prename descclassname"><span class="pre"><span class="highlighted">string</span>.</span></span><span class="sig-name descname"><span class="pre">capwords</span></span><span class="sig-paren">(</span><i class="sig-param"><span class="n"><span class="pre">s</span></span></i>, <i class="sig-param"><span class="n"><span class="pre">sep</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></i><span class="sig-paren">)</span></section><section id="helper-functions" style="text-align: left;"> </section><section id="helper-functions" style="text-align: left;">Split the argument into words using <a class="reference internal" href="https://docs.python.org/3/library/stdtypes.html#str.split" title="str.split"><code class="xref py py-meth docutils literal notranslate"><span class="pre">str.split()</span></code></a>, capitalize each word
using <a class="reference internal" href="https://docs.python.org/3/library/stdtypes.html#str.capitalize" title="str.capitalize"><code class="xref py py-meth docutils literal notranslate"><span class="pre">str.capitalize()</span></code></a>, and join the capitalized words using
<a class="reference internal" href="https://docs.python.org/3/library/stdtypes.html#str.join" title="str.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">str.join()</span></code></a>. If the optional second argument <i>sep</i> is absent
or <code class="docutils literal notranslate"><span class="pre">None</span></code>, runs of whitespace characters are replaced by a single space
and leading and trailing whitespace are removed, otherwise <i>sep</i> is used to
split and join the words.<dl class="py function"><dd>
<br /></dd></dl>
</section>
</dd></dl>
</section><pre class="showoutput" id="log"> Source: https://docs.python.org</pre><p></p>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-46576007807204753862023-10-21T15:11:00.005+03:002023-10-21T15:22:09.954+03:00Python Generators/List comprehension comparison<div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: #c586c0;">import</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">time</span><span style="color: #cccccc;">, </span><span style="color: #4ec9b0;">sys</span></div><br /><div><span style="color: #9cdcfe;">genstartime</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">time</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">perf_counter</span><span style="color: #cccccc;">()</span></div><div><span style="color: #9cdcfe;">gensquares</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> (</span><span style="color: #9cdcfe;">x</span><span style="color: #d4d4d4;">**</span><span style="color: #b5cea8;">2</span><span style="color: #cccccc;"> </span><span style="color: #c586c0;">for</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">x</span><span style="color: #cccccc;"> </span><span style="color: #c586c0;">in</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">range</span><span style="color: #cccccc;">(</span><span style="color: #b5cea8;">500000</span><span style="color: #cccccc;">))</span></div><div><span style="color: #6a9955;"># print(time.perf_counter() - genstartime, type(gensquares))</span></div><div><span style="color: #9cdcfe;">gencompstartime</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">time</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">perf_counter</span><span style="color: #cccccc;">()</span></div><div><span style="color: #9cdcfe;">finalgenlist</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> [</span><span style="color: #9cdcfe;">square</span><span style="color: #cccccc;"> </span><span style="color: #c586c0;">for</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">square</span><span style="color: #cccccc;"> </span><span style="color: #c586c0;">in</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">gensquares</span><span style="color: #cccccc;">]</span></div><div><span style="color: #dcdcaa;">print</span><span style="color: #cccccc;">(</span></div><div><span style="color: #cccccc;"> </span><span style="color: #ce9178;">"Generator with list comprehension. Generator time:"</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">time</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">perf_counter</span><span style="color: #cccccc;">() </span><span style="color: #d4d4d4;">-</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">gencompstartime</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;"> </span><span style="color: #ce9178;">"Final time:"</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">time</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">perf_counter</span><span style="color: #cccccc;">() </span><span style="color: #d4d4d4;">-</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">genstartime</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;">)</span></div><br /><div><span style="color: #9cdcfe;">genstartime</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">time</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">perf_counter</span><span style="color: #cccccc;">()</span></div><div><span style="color: #9cdcfe;">gensquares</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> (</span><span style="color: #9cdcfe;">x</span><span style="color: #d4d4d4;">**</span><span style="color: #b5cea8;">2</span><span style="color: #cccccc;"> </span><span style="color: #c586c0;">for</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">x</span><span style="color: #cccccc;"> </span><span style="color: #c586c0;">in</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">range</span><span style="color: #cccccc;">(</span><span style="color: #b5cea8;">500000</span><span style="color: #cccccc;">))</span></div><div><span style="color: #6a9955;"># print(time.perf_counter() - genstartime, type(gensquares))</span></div><div><span style="color: #9cdcfe;">gencompstartime</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">time</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">perf_counter</span><span style="color: #cccccc;">()</span></div><div><span style="color: #9cdcfe;">finalgenlist</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">list</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">gensquares</span><span style="color: #cccccc;">)</span></div><div><span style="color: #dcdcaa;">print</span><span style="color: #cccccc;">(</span></div><div><span style="color: #cccccc;"> </span><span style="color: #ce9178;">"Generator with list(). Generator time:"</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">time</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">perf_counter</span><span style="color: #cccccc;">() </span><span style="color: #d4d4d4;">-</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">gencompstartime</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;"> </span><span style="color: #ce9178;">"Final time:"</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">time</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">perf_counter</span><span style="color: #cccccc;">() </span><span style="color: #d4d4d4;">-</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">genstartime</span><span style="color: #cccccc;">,</span></div><div><span style="color: #cccccc;">)</span></div><div><span style="color: #dcdcaa;">print</span><span style="color: #cccccc;">(</span><span style="color: #ce9178;">'Memory size of generator in bytes:'</span><span style="color: #cccccc;">, </span><span style="color: #4ec9b0;">sys</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">getsizeof</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">gensquares</span><span style="color: #cccccc;">),</span></div><div><span style="color: #cccccc;"> </span><span style="color: #ce9178;">'Memory size of list in bytes:'</span><span style="color: #cccccc;">, </span><span style="color: #4ec9b0;">sys</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">getsizeof</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">finalgenlist</span><span style="color: #cccccc;">))</span></div><div><span style="color: #6a9955;"># An important thing to note is that generators iterate over an object lazily,</span></div><div><span style="color: #6a9955;"># meaning they do not store their contents in memory.</span></div><div><span style="color: #6a9955;"># listfromgen = list(gensquares)</span></div><div><span style="color: #6a9955;"># print(listfromgen, len(listfromgen), sys.getsizeof(listfromgen)) # [] 0 56</span></div><div><span style="color: #6a9955;"># print(len(finalgenlist)) # list kept in memory, len equal to range</span></div><br /><div><span style="color: #9cdcfe;">liststartime</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">time</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">perf_counter</span><span style="color: #cccccc;">()</span></div><div><span style="color: #9cdcfe;">listsquares</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> [</span><span style="color: #9cdcfe;">x</span><span style="color: #d4d4d4;">**</span><span style="color: #b5cea8;">2</span><span style="color: #cccccc;"> </span><span style="color: #c586c0;">for</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">x</span><span style="color: #cccccc;"> </span><span style="color: #c586c0;">in</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">range</span><span style="color: #cccccc;">(</span><span style="color: #b5cea8;">500000</span><span style="color: #cccccc;">)]</span></div><div><span style="color: #dcdcaa;">print</span><span style="color: #cccccc;">(</span></div><div><span style="color: #cccccc;"> </span><span style="color: #ce9178;">"Simple list comprehension"</span><span style="color: #cccccc;">, </span><span style="color: #4ec9b0;">time</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">perf_counter</span><span style="color: #cccccc;">() </span><span style="color: #d4d4d4;">-</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">liststartime</span><span style="color: #cccccc;">, </span><span style="color: #4ec9b0;">type</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">listsquares</span><span style="color: #cccccc;">)</span></div><div><span style="color: #cccccc;">)</span></div><div><span style="color: #6a9955;"># print( 'Memory size after list comprehension in bytes:', sys.getsizeof(listsquares))</span></div> </div></div></div></div><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;">Results with Python 3.11.4:</div><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;">Generator with list comprehension. Generator time: 0.09394780000002356 Final time: 0.09395289999883971<br />Generator with list(). Generator time: 0.0871331000016653 Final time: 0.08714600000166683<br />Memory size of generator in bytes: 208 Memory size of list in bytes: 4167352<br />Simple list comprehension 0.06546270000035292 <class 'list'><br /> <br />Generator with list comprehension. Generator time: 0.08868479999728152 Final time: 0.08870200000092154<br />Generator with list(). Generator time: 0.08478610000020126 Final time: 0.08480150000104913<br />Memory size of generator in bytes: 208 Memory size of list in bytes: 4167352<br />Simple list comprehension 0.06996629999775905 <class 'list'><br /><br />Generator with list comprehension. Generator time: 0.08237219999864465 Final time: 0.08237809999991441<br />Generator with list(). Generator time: 0.09145460000218009 Final time: 0.09146870000040508<br />Memory size of generator in bytes: 208 Memory size of list in bytes: 4167352<br />Simple list comprehension 0.0625220999972953 <class 'list'></div>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-78836768380224881462023-10-14T12:58:00.002+03:002023-10-14T12:58:39.000+03:00Add Global Jinja Variables for Quart/Flask<div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: #9cdcfe;">app</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #4ec9b0;">Quart</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">__name__</span><span style="color: #cccccc;">, </span><span style="color: #9cdcfe;">template_folder</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">'templates'</span><span style="color: #cccccc;">, </span><span style="color: #9cdcfe;">static_folder</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">'static'</span><span style="color: #cccccc;">)</span></div><div><span style="color: #9cdcfe;"></span></div><span style="color: #9cdcfe;">app</span><span style="color: #cccccc;">.</span><span style="color: #9cdcfe;">jinja_env</span><span style="color: #cccccc;">.</span><span style="color: #9cdcfe;">globals</span><span style="color: #cccccc;">[</span><span style="color: #ce9178;">'emojiflags'</span><span style="color: #cccccc;">] </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #9cdcfe;">emojiflags</span><span style="color: #9cdcfe;"> </span></div><p> or <br /></p><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: #9cdcfe;">app</span><span style="color: #cccccc;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #cccccc;"> </span><span style="color: #cccccc;"></span><span style="color: #4ec9b0;">Flask</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">__name__</span><span style="color: #cccccc;">, </span><span style="color: #9cdcfe;">template_folder</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">'templates'</span><span style="color: #cccccc;">, </span><span style="color: #9cdcfe;">static_folder</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">'static'</span><span style="color: #cccccc;">)</span></div><div><span style="color: #9cdcfe;"></span></div><div><div style="background-color: #1f1f1f; color: #cccccc; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: #9cdcfe;">app</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">add_template_global</span><span style="color: #cccccc;">(</span><span style="color: #9cdcfe;">name</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">'emojiflags'</span><span style="color: #cccccc;">, </span><span style="color: #9cdcfe;">f</span><span style="color: #d4d4d4;">=</span><span style="color: #9cdcfe;">emojiflags</span><span style="color: #cccccc;">) </span></div></div></div></div>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-37434569370767654242023-10-11T17:36:00.007+03:002023-10-14T21:22:50.495+03:00CSS Default Browser Values for HTML Elements
<table border="0" cellspacing="0">
<colgroup width="482"></colgroup>
<colgroup width="427"></colgroup>
<tbody><tr>
<td align="center" height="21"><b><span style="font-family: Times New Roman;">Element</span></b></td>
<td align="center"><b><span style="font-family: Times New Roman;">Default CSS Value</span></b></td>
</tr>
<tr>
<td align="left" height="59"><span style="font-family: Times New Roman;">a:link</span></td>
<td align="left"><span style="font-family: Times New Roman;">color: (internal value);<br />text-decoration: underline;<br />cursor: auto;</span></td>
</tr>
<tr>
<td align="left" height="59"><span style="font-family: Times New Roman;">a:visited</span></td>
<td align="left"><span style="font-family: Times New Roman;">color: (internal value);<br />text-decoration: underline;<br />cursor: auto;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">a:link:active</span></td>
<td align="left"><span style="font-family: Times New Roman;">color: (internal value);</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">a:visited:active</span></td>
<td align="left"><span style="font-family: Times New Roman;">color: (internal value);</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">abbr</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="40"><span style="font-family: Times New Roman;">address</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />font-style: italic;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">area</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: none;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">article</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block; </span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">aside</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block; </span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">audio</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">b</span></td>
<td align="left"><span style="font-family: Times New Roman;">font-weight: bold;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">base</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">bdi</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">bdo</span></td>
<td align="left"><span style="font-family: Times New Roman;">unicode-bidi: bidi-override;</span></td>
</tr>
<tr>
<td align="left" height="97"><span style="font-family: Times New Roman;">blockquote</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />margin-top: 1em;<br />margin-bottom: 1em;<br />margin-left: 40px;<br />margin-right: 40px;</span></td>
</tr>
<tr>
<td align="left" height="40"><span style="font-family: Times New Roman;">body</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />margin: 8px;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">body:focus</span></td>
<td align="left"><span style="font-family: Times New Roman;">outline: none;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">br</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">button</span></td>
<td align="left"><span style="font-family: Times New Roman;">None</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">canvas</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="40"><span style="font-family: Times New Roman;">caption</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: table-caption;<br />text-align: center;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">cite</span></td>
<td align="left"><span style="font-family: Times New Roman;">font-style: italic;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">code</span></td>
<td align="left"><span style="font-family: Times New Roman;">font-family: monospace;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">col</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: table-column;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">colgroup</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: table-column-group</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">datalist</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: none;</span></td>
</tr>
<tr>
<td align="left" height="40"><span style="font-family: Times New Roman;">dd</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />margin-left: 40px;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">del</span></td>
<td align="left"><span style="font-family: Times New Roman;">text-decoration: line-through;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">details</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">dfn</span></td>
<td align="left"><span style="font-family: Times New Roman;">font-style: italic;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">dialog</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">div</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;</span></td>
</tr>
<tr>
<td align="left" height="97"><span style="font-family: Times New Roman;">dl</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />margin-top: 1em;<br />margin-bottom: 1em;<br />margin-left: 0;<br />margin-right: 0;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">dt</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">em</span></td>
<td align="left"><span style="font-family: Times New Roman;">font-style: italic;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">embed:focus</span></td>
<td align="left"><span style="font-family: Times New Roman;">outline: none;</span></td>
</tr>
<tr>
<td align="left" height="155"><span style="font-family: Times New Roman;">fieldset</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />margin-left: 2px;<br />margin-right: 2px;<br />padding-top: 0.35em;<br />padding-bottom: 0.625em;<br />padding-left: 0.75em;<br />padding-right: 0.75em;<br />border: 2px groove (internal value);</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">figcaption</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;</span></td>
</tr>
<tr>
<td align="left" height="97"><span style="font-family: Times New Roman;">figure</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />margin-top: 1em;<br />margin-bottom: 1em;<br />margin-left: 40px;<br />margin-right: 40px;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">footer</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;</span></td>
</tr>
<tr>
<td align="left" height="40"><span style="font-family: Times New Roman;">form</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />margin-top: 0em;</span></td>
</tr>
<tr>
<td align="left" height="136"><span style="font-family: Times New Roman;">h1</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />font-size: 2em;<br />margin-top: 0.67em;<br />margin-bottom: 0.67em;<br />margin-left: 0;<br />margin-right: 0;<br />font-weight: bold;</span></td>
</tr>
<tr>
<td align="left" height="136"><span style="font-family: Times New Roman;">h2</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />font-size: 1.5em;<br />margin-top: 0.83em;<br />margin-bottom: 0.83em;<br />margin-left: 0;<br />margin-right: 0;<br />font-weight: bold;</span></td>
</tr>
<tr>
<td align="left" height="136"><span style="font-family: Times New Roman;">h3</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />font-size: 1.17em;<br />margin-top: 1em;<br />margin-bottom: 1em;<br />margin-left: 0;<br />margin-right: 0;<br />font-weight: bold;</span></td>
</tr>
<tr>
<td align="left" height="116"><span style="font-family: Times New Roman;">h4</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />margin-top: 1.33em;<br />margin-bottom: 1.33em;<br />margin-left: 0;<br />margin-right: 0;<br />font-weight: bold;</span></td>
</tr>
<tr>
<td align="left" height="136"><span style="font-family: Times New Roman;">h5</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />font-size: .83em;<br />margin-top: 1.67em;<br />margin-bottom: 1.67em;<br />margin-left: 0;<br />margin-right: 0;<br />font-weight: bold;</span></td>
</tr>
<tr>
<td align="left" height="136"><span style="font-family: Times New Roman;">h6</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />font-size: .67em;<br />margin-top: 2.33em;<br />margin-bottom: 2.33em;<br />margin-left: 0;<br />margin-right: 0;<br />font-weight: bold;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">head</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: none;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">header</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;</span></td>
</tr>
<tr>
<td align="left" height="136"><span style="font-family: Times New Roman;">hr</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />margin-top: 0.5em;<br />margin-bottom: 0.5em;<br />margin-left: auto;<br />margin-right: auto;<br />border-style: inset;<br />border-width: 1px;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">html</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">html:focus</span></td>
<td align="left"><span style="font-family: Times New Roman;">outline: none;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">i</span></td>
<td align="left"><span style="font-family: Times New Roman;">font-style: italic;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">iframe:focus</span></td>
<td align="left"><span style="font-family: Times New Roman;">outline: none;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">iframe[seamless]</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">img</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: inline-block;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">input</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">ins</span></td>
<td align="left"><span style="font-family: Times New Roman;">text-decoration: underline;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">kbd</span></td>
<td align="left"><span style="font-family: Times New Roman;">font-family: monospace;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">label</span></td>
<td align="left"><span style="font-family: Times New Roman;">cursor: default;</span></td>
</tr>
<tr>
<td align="left" height="78"><span style="font-family: Times New Roman;">legend</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />padding-left: 2px;<br />padding-right: 2px;<br />border: none;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">li</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: list-item;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">link</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: none;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">main</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">map</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: inline;</span></td>
</tr>
<tr>
<td align="left" height="40"><span style="font-family: Times New Roman;">mark</span></td>
<td align="left"><span style="font-family: Times New Roman;">background-color: yellow;<br />color: black;</span></td>
</tr>
<tr>
<td align="left" height="136"><span style="font-family: Times New Roman;">menu</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />list-style-type: disc;<br />margin-top: 1em;<br />margin-bottom: 1em;<br />margin-left: 0;<br />margin-right: 0;<br />padding-left: 40px;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">menuitem</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">meta</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">meter</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">nav</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">noscript</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">object:focus</span></td>
<td align="left"><span style="font-family: Times New Roman;">outline: none;</span></td>
</tr>
<tr>
<td align="left" height="136"><span style="font-family: Times New Roman;">ol</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />list-style-type: decimal;<br />margin-top: 1em;<br />margin-bottom: 1em;<br />margin-left: 0;<br />margin-right: 0;<br />padding-left: 40px;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">optgroup</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">option</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">output</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: inline;</span></td>
</tr>
<tr>
<td align="left" height="97"><span style="font-family: Times New Roman;">p</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />margin-top: 1em;<br />margin-bottom: 1em;<br />margin-left: 0;<br />margin-right: 0;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">param</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: none;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">picture</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="78"><span style="font-family: Times New Roman;">pre</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />font-family: monospace;<br />white-space: pre;<br />margin: 1em 0;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">progress</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">q</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: inline;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">q::before</span></td>
<td align="left"><span style="font-family: Times New Roman;">content: open-quote;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">q::after</span></td>
<td align="left"><span style="font-family: Times New Roman;">content: close-quote;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">rp</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">rt</span></td>
<td align="left"><span style="font-family: Times New Roman;">line-height: normal;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">ruby</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">s</span></td>
<td align="left"><span style="font-family: Times New Roman;">text-decoration: line-through;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">samp</span></td>
<td align="left"><span style="font-family: Times New Roman;">font-family: monospace;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">script</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: none;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">section</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">select</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">small</span></td>
<td align="left"><span style="font-family: Times New Roman;">font-size: smaller;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">source</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">span</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">strike</span></td>
<td align="left"><span style="font-family: Times New Roman;">text-decoration: line-through;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">strong</span></td>
<td align="left"><span style="font-family: Times New Roman;">font-weight: bold;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">style</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: none;</span></td>
</tr>
<tr>
<td align="left" height="40"><span style="font-family: Times New Roman;">sub</span></td>
<td align="left"><span style="font-family: Times New Roman;">vertical-align: sub;<br />font-size: smaller;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">summary</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;</span></td>
</tr>
<tr>
<td align="left" height="40"><span style="font-family: Times New Roman;">sup</span></td>
<td align="left"><span style="font-family: Times New Roman;">vertical-align: super;<br />font-size: smaller;</span></td>
</tr>
<tr>
<td align="left" height="78"><span style="font-family: Times New Roman;">table</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: table;<br />border-collapse: separate;<br />border-spacing: 2px;<br />border-color: gray;</span></td>
</tr>
<tr>
<td align="left" height="59"><span style="font-family: Times New Roman;">tbody</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: table-row-group;<br />vertical-align: middle;<br />border-color: inherit;</span></td>
</tr>
<tr>
<td align="left" height="40"><span style="font-family: Times New Roman;">td</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: table-cell;<br />vertical-align: inherit;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">template</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">textarea</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="59"><span style="font-family: Times New Roman;">tfoot</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: table-footer-group;<br />vertical-align: middle;<br />border-color: inherit;</span></td>
</tr>
<tr>
<td align="left" height="78"><span style="font-family: Times New Roman;">th</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: table-cell;<br />vertical-align: inherit;<br />font-weight: bold;<br />text-align: center;</span></td>
</tr>
<tr>
<td align="left" height="59"><span style="font-family: Times New Roman;">thead</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: table-header-group;<br />vertical-align: middle;<br />border-color: inherit;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">time</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">title</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: none;</span></td>
</tr>
<tr>
<td align="left" height="59"><span style="font-family: Times New Roman;">tr</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: table-row;<br />vertical-align: inherit;<br />border-color: inherit;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">track</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">u</span></td>
<td align="left"><span style="font-family: Times New Roman;">text-decoration: underline;</span></td>
</tr>
<tr>
<td align="left" height="136"><span style="font-family: Times New Roman;">ul</span></td>
<td align="left"><span style="font-family: Times New Roman;">display: block;<br />list-style-type: disc;<br />margin-top: 1em;<br />margin-bottom: 1 em;<br />margin-left: 0;<br />margin-right: 0;<br />padding-left: 40px;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">var</span></td>
<td align="left"><span style="font-family: Times New Roman;">font-style: italic;</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">video</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21"><span style="font-family: Times New Roman;">wbr</span></td>
<td align="left"><span style="font-family: Times New Roman;">None.</span></td>
</tr>
<tr>
<td align="left" height="21">html</td>
<td align="left">display: block;</td>
</tr>
<tr>
<td align="left" height="21">html:focus</td>
<td align="left">outline: none;</td>
</tr>
<tr>
<td align="left" height="21">i</td>
<td align="left">font-style: italic;</td>
</tr>
<tr>
<td align="left" height="21">iframe:focus</td>
<td align="left">outline: none;</td>
</tr>
<tr>
<td align="left" height="21">iframe[seamless]</td>
<td align="left">display: block;</td>
</tr>
<tr>
<td align="left" height="21">img</td>
<td align="left">display: inline-block;</td>
</tr>
<tr>
<td align="left" height="21">input</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">ins</td>
<td align="left">text-decoration: underline;</td>
</tr>
<tr>
<td align="left" height="21">kbd</td>
<td align="left">font-family: monospace;</td>
</tr>
<tr>
<td align="left" height="21">label</td>
<td align="left">cursor: default;</td>
</tr>
<tr>
<td align="left" height="21">legend</td>
<td align="left">display: block;</td>
</tr>
<tr>
<td align="left" height="21">padding-left: 2px;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">padding-right: 2px;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">border: none;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">li</td>
<td align="left">display: list-item;</td>
</tr>
<tr>
<td align="left" height="21">link</td>
<td align="left">display: none;</td>
</tr>
<tr>
<td align="left" height="21">main</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">map</td>
<td align="left">display: inline;</td>
</tr>
<tr>
<td align="left" height="21">mark</td>
<td align="left">background-color: yellow;</td>
</tr>
<tr>
<td align="left" height="21">color: black;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">menu</td>
<td align="left">display: block;</td>
</tr>
<tr>
<td align="left" height="21">list-style-type: disc;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">margin-top: 1em;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">margin-bottom: 1em;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">margin-left: 0;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">margin-right: 0;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">padding-left: 40px;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">menuitem</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">meta</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">meter</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">nav</td>
<td align="left">display: block;</td>
</tr>
<tr>
<td align="left" height="21">noscript</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">object:focus</td>
<td align="left">outline: none;</td>
</tr>
<tr>
<td align="left" height="21">ol</td>
<td align="left">display: block;</td>
</tr>
<tr>
<td align="left" height="21">list-style-type: decimal;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">margin-top: 1em;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">margin-bottom: 1em;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">margin-left: 0;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">margin-right: 0;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">padding-left: 40px;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">optgroup</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">option</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">output</td>
<td align="left">display: inline;</td>
</tr>
<tr>
<td align="left" height="21">p</td>
<td align="left">display: block;</td>
</tr>
<tr>
<td align="left" height="21">margin-top: 1em;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">margin-bottom: 1em;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">margin-left: 0;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">margin-right: 0;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">param</td>
<td align="left">display: none;</td>
</tr>
<tr>
<td align="left" height="21">picture</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">pre</td>
<td align="left">display: block;</td>
</tr>
<tr>
<td align="left" height="21">font-family: monospace;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">white-space: pre;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">margin: 1em 0;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">progress</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">q</td>
<td align="left">display: inline;</td>
</tr>
<tr>
<td align="left" height="21">q::before</td>
<td align="left">content: open-quote;</td>
</tr>
<tr>
<td align="left" height="21">q::after</td>
<td align="left">content: close-quote;</td>
</tr>
<tr>
<td align="left" height="21">rp</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">rt</td>
<td align="left">line-height: normal;</td>
</tr>
<tr>
<td align="left" height="21">ruby</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">s</td>
<td align="left">text-decoration: line-through;</td>
</tr>
<tr>
<td align="left" height="21">samp</td>
<td align="left">font-family: monospace;</td>
</tr>
<tr>
<td align="left" height="21">script</td>
<td align="left">display: none;</td>
</tr>
<tr>
<td align="left" height="21">section</td>
<td align="left">display: block;</td>
</tr>
<tr>
<td align="left" height="21">select</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">small</td>
<td align="left">font-size: smaller;</td>
</tr>
<tr>
<td align="left" height="21">source</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">span</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">strike</td>
<td align="left">text-decoration: line-through;</td>
</tr>
<tr>
<td align="left" height="21">strong</td>
<td align="left">font-weight: bold;</td>
</tr>
<tr>
<td align="left" height="21">style</td>
<td align="left">display: none;</td>
</tr>
<tr>
<td align="left" height="21">sub</td>
<td align="left">vertical-align: sub;</td>
</tr>
<tr>
<td align="left" height="21">font-size: smaller;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">summary</td>
<td align="left">display: block;</td>
</tr>
<tr>
<td align="left" height="21">sup</td>
<td align="left">vertical-align: super;</td>
</tr>
<tr>
<td align="left" height="21">font-size: smaller;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">table</td>
<td align="left">display: table;</td>
</tr>
<tr>
<td align="left" height="21">border-collapse: separate;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">border-spacing: 2px;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">border-color: gray;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">tbody</td>
<td align="left">display: table-row-group;</td>
</tr>
<tr>
<td align="left" height="21">vertical-align: middle;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">border-color: inherit;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">td</td>
<td align="left">display: table-cell;</td>
</tr>
<tr>
<td align="left" height="21">vertical-align: inherit;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">template</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">textarea</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">tfoot</td>
<td align="left">display: table-footer-group;</td>
</tr>
<tr>
<td align="left" height="21">vertical-align: middle;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">border-color: inherit;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">th</td>
<td align="left">display: table-cell;</td>
</tr>
<tr>
<td align="left" height="21">vertical-align: inherit;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">font-weight: bold;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">text-align: center;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">thead</td>
<td align="left">display: table-header-group;</td>
</tr>
<tr>
<td align="left" height="21">vertical-align: middle;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">border-color: inherit;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">time</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">title</td>
<td align="left">display: none;</td>
</tr>
<tr>
<td align="left" height="21">tr</td>
<td align="left">display: table-row;</td>
</tr>
<tr>
<td align="left" height="21">vertical-align: inherit;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">border-color: inherit;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">track</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">u</td>
<td align="left">text-decoration: underline;</td>
</tr>
<tr>
<td align="left" height="21">ul</td>
<td align="left">display: block;</td>
</tr>
<tr>
<td align="left" height="21">list-style-type: disc;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">margin-top: 1em;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">margin-bottom: 1 em;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">margin-left: 0;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">margin-right: 0;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">padding-left: 40px;</td>
<td align="left"><br /></td>
</tr>
<tr>
<td align="left" height="21">var</td>
<td align="left">font-style: italic;</td>
</tr>
<tr>
<td align="left" height="21">video</td>
<td align="left">None.</td>
</tr>
<tr>
<td align="left" height="21">wbr</td>
<td align="left">None.</td>
</tr>
</tbody></table><div style="text-align: center;">
***** </div><div style="text-align: center;"><table class="ws-table-all notranslate"><tbody><tr><th style="width: 20%;">Selector</th>
<th style="width: 20%;">Example</th>
<th>Example description</th>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_class.php">.<i>class</i></a></td>
<td class="notranslate">.intro</td>
<td>Selects all elements with class="intro"</td>
</tr>
<tr>
<td><i>.class1.class2</i></td>
<td class="notranslate">.name1.name2</td>
<td>Selects all elements with both <i>name1</i> and <i>name2</i> set
within its class attribute</td>
</tr>
<tr>
<td><i>.class1 .class2</i></td>
<td class="notranslate">.name1 .name2</td>
<td>Selects all elements with <i>name2</i> that is a descendant of an
element with <i>name1</i></td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_id.php">#<i>id</i></a></td>
<td class="notranslate">#firstname</td>
<td>Selects the element with id="firstname"</td>
</tr> <tr>
<td><a href="https://www.w3schools.com/cssref/sel_all.php">*</a></td>
<td class="notranslate">*</td>
<td>Selects all elements</td>
</tr>
<tr>
<td><i><a href="https://www.w3schools.com/cssref/sel_element.php">element</a></i></td>
<td class="notranslate">p</td>
<td>Selects all <p> elements</td>
</tr>
<tr>
<td><i><a href="https://www.w3schools.com/cssref/sel_element_class.php">element.class</a></i></td>
<td class="notranslate">p.intro</td>
<td>Selects all <p> elements with class="intro"</td>
</tr>
<tr>
<td><i><a href="https://www.w3schools.com/cssref/sel_element_comma.php">element,element</a></i></td>
<td class="notranslate">div, p</td>
<td>Selects all <div> elements and all <p> elements</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_element_element.php"><i>element</i> <i>element</i></a></td>
<td class="notranslate">div p</td>
<td>Selects all <p> elements inside <div> elements</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_element_gt.php"><i>element</i>><i>element</i></a></td>
<td class="notranslate">div > p</td>
<td>Selects all <p> elements where the parent is a <div> element</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_element_pluss.php"><i>element</i>+<i>element</i></a></td>
<td class="notranslate">div + p</td>
<td>Selects the first <p> element that is placed immediately after <div> elements</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_gen_sibling.php"><i>element1</i>~<i>element2</i></a></td>
<td>p ~ ul</td>
<td>Selects every <ul> element that is preceded by a <p> element</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_attribute.php">[<i>attribute</i>]</a></td>
<td class="notranslate">[target]</td>
<td>Selects all elements with a target attribute</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_attribute_value.php">[<i>attribute</i>=<i>value</i>]</a></td>
<td class="notranslate">[target="_blank"]</td>
<td>Selects all elements with target="_blank"</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_attribute_value_contains.php">[<i>attribute</i>~=<i>value</i>]</a></td>
<td class="notranslate">[title~="flower"]</td>
<td>Selects all elements with a title attribute containing the word "flower"</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_attribute_value_lang.php">[<i>attribute</i>|=<i>value</i>]</a></td>
<td class="notranslate">[lang|="en"]</td>
<td>Selects all elements with a lang attribute value equal to "en" or
starting with "en-"</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_attr_begin.php">[<i>attribute</i>^=<i>value</i>]</a></td>
<td>a[href^="https"]</td>
<td>Selects every <a> element whose href attribute value begins with "https"</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_attr_end.php">[<i>attribute</i>$=<i>value</i>]</a></td>
<td>a[href$=".pdf"]</td>
<td>Selects every <a> element whose href attribute value ends with ".pdf"</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_attr_contain.php">[<i>attribute</i>*=<i>value</i>]</a></td>
<td>a[href*="w3schools"]</td>
<td>Selects every <a> element whose href attribute value contains the substring "w3schools"</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_active.php">:active</a></td>
<td class="notranslate">a:active</td>
<td>Selects the active link</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_after.php">::after</a></td>
<td class="notranslate">p::after</td>
<td>Insert something after the content of each <p> element</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_before.php">::before</a></td>
<td class="notranslate">p::before</td>
<td>Insert something before the content of each <p> element</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_checked.php">:checked</a></td>
<td>input:checked</td>
<td>Selects every checked <input> element</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_default.php">:default</a></td>
<td>input:default</td>
<td>Selects the default <input> element</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_disabled.php">:disabled</a></td>
<td>input:disabled</td>
<td>Selects every disabled <input> element</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_empty.php">:empty</a></td>
<td>p:empty</td>
<td>Selects every <p> element that has no children (including text nodes)</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_enabled.php">:enabled</a></td>
<td>input:enabled</td>
<td>Selects every enabled <input> element</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_firstchild.php">:first-child</a></td>
<td class="notranslate">p:first-child</td>
<td>Selects every <p> element that is the first child of its parent</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_firstletter.php">::first-letter</a></td>
<td class="notranslate">p::first-letter</td>
<td>Selects the first letter of every <p> element</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_firstline.php">::first-line</a></td>
<td class="notranslate">p::first-line</td>
<td>Selects the first line of every <p> element</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_first-of-type.php">:first-of-type</a></td>
<td>p:first-of-type</td>
<td>Selects every <p> element that is the first <p> element of its parent</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_focus.php">:focus</a></td>
<td class="notranslate">input:focus</td>
<td>Selects the input element which has focus</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_fullscreen.php">:fullscreen</a></td>
<td class="notranslate">:fullscreen</td>
<td>Selects the element that is in full-screen mode</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_hover.php">:hover</a></td>
<td class="notranslate">a:hover</td>
<td>Selects links on mouse over</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_in-range.php">:in-range</a></td>
<td class="notranslate">input:in-range</td>
<td>Selects input elements with a value within a specified range</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_indeterminate.php">:indeterminate</a></td>
<td class="notranslate">input:indeterminate</td>
<td>Selects input elements that are in an indeterminate state</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_invalid.php">:invalid</a></td>
<td class="notranslate">input:invalid</td>
<td>Selects all input elements with an invalid value</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_lang.php">:lang(<i>language</i>)</a></td>
<td class="notranslate">p:lang(it)</td>
<td>Selects every <p> element with a lang attribute equal to "it" (Italian)</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_last-child.php">:last-child</a></td>
<td>p:last-child</td>
<td>Selects every <p> element that is the last child of its parent</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_last-of-type.php">:last-of-type</a></td>
<td>p:last-of-type</td>
<td>Selects every <p> element that is the last <p> element of its parent</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_link.php">:link</a></td>
<td class="notranslate">a:link</td>
<td>Selects all unvisited links</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_marker.php">::marker</a></td>
<td>::marker</td>
<td>Selects the markers of list items</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_not.php">:not(<i>selector</i>)</a></td>
<td>:not(p)</td>
<td>Selects every element that is not a <p> element</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_nth-child.php">:nth-child(<i>n</i>)</a></td>
<td>p:nth-child(2)</td>
<td>Selects every <p> element that is the second child of its parent</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_nth-last-child.php">:nth-last-child(<i>n</i>)</a></td>
<td>p:nth-last-child(2)</td>
<td>Selects every <p> element that is the second child of its parent, counting from the last child</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_nth-last-of-type.php">:nth-last-of-type(<i>n</i>)</a></td>
<td>p:nth-last-of-type(2)</td>
<td>Selects every <p> element that is the second <p> element of its parent, counting from the last child</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_nth-of-type.php">:nth-of-type(<i>n</i>)</a></td>
<td>p:nth-of-type(2)</td>
<td>Selects every <p> element that is the second <p> element of its parent</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_only-of-type.php">:only-of-type</a></td>
<td>p:only-of-type</td>
<td>Selects every <p> element that is the only <p> element of its parent</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_only-child.php">:only-child</a></td>
<td>p:only-child</td>
<td>Selects every <p> element that is the only child of its parent</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_optional.php">:optional</a></td>
<td class="notranslate">input:optional</td>
<td>Selects input elements with no "required" attribute</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_out-of-range.php">:out-of-range</a></td>
<td class="notranslate">input:out-of-range</td>
<td>Selects input elements with a value outside a specified range</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_placeholder.php">::placeholder</a></td>
<td class="notranslate">input::placeholder</td>
<td>Selects input elements with the "placeholder" attribute specified</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_read-only.php">:read-only</a></td>
<td class="notranslate">input:read-only</td>
<td>Selects input elements with the "readonly" attribute specified</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_read-write.php">:read-write</a></td>
<td class="notranslate">input:read-write</td>
<td>Selects input elements with the "readonly" attribute NOT specified</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_required.php">:required</a></td>
<td class="notranslate">input:required</td>
<td>Selects input elements with the "required" attribute specified</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_root.php">:root</a></td>
<td>:root</td>
<td>Selects the document's root element</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_selection.php">::selection</a></td>
<td>::selection</td>
<td>Selects the portion of an element that is selected by a user</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_target.php">:target</a></td>
<td>#news:target </td>
<td>Selects the current active #news element (clicked on a URL containing that anchor name)</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_valid.php">:valid</a></td>
<td class="notranslate">input:valid</td>
<td>Selects all input elements with a valid value</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_visited.php">:visited</a></td>
<td class="notranslate">a:visited</td>
<td>Selects all visited links</td></tr></tbody></table> ******</div><div style="text-align: left;"><h2><span style="font-size: medium;">All CSS Combinator Selectors</span></h2>
<table class="ws-table-all notranslate"><tbody><tr>
<th style="width: 25%;">Selector</th>
<th style="width: 15%;">Example</th>
<th>Example description</th>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_element_element.asp"><i>element element</i></a></td>
<td class="notranslate">div p</td>
<td>Selects all <p> elements inside <div> elements</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_element_gt.asp"><i>element>element</i></a></td>
<td class="notranslate">div > p</td>
<td>Selects all <p> elements where the parent is a <div> element</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_element_pluss.asp"><i>element+element</i></a></td>
<td class="notranslate">div + p</td>
<td>Selects the first <p> element that are placed immediately after <div> elements</td>
</tr>
<tr>
<td><a href="https://www.w3schools.com/cssref/sel_gen_sibling.asp"><i>element1~element2</i></a></td>
<td>p ~ ul</td>
<td>Selects every <ul> element that are preceded by a <p> element</td></tr></tbody></table> </div>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-75304402753628528752023-10-11T17:20:00.005+03:002023-10-11T17:24:51.610+03:00Custom Styling Radio Input Dark Theme<p><style><br />div {<br /> background: black;<br /> opacity: 0.8;<br />}<br />input[type="radio"] {<br /> position: absolute;<br /> opacity: 0;<br />}<br /><br />input[type="radio"] + .radio {<br /> border: 1px solid cyan;<br /> border-radius: 50%;<br /> display: inline-block;<br /> width: 10px;<br /> height: 10px;<br />}<br /><br />input[type="radio"]:checked + .radio {<br /> background: cyan;<br />}<br />span.whitetext {<br /> color:white;<br />}<br /></style><br /><br /><div><br /><label for="male"><br /> <input id="male" type="radio" name="gender" value="male" /><br /> <span class="radio"></span><br /> <span class="whitetext">Male</span><br /></label><br /><br /><label for="female"><br /> <input id="female" type="radio" name="gender" value="female" checked /><br /> <span class="radio"></span><br /> <span class="whitetext">Female</span><br /></label><br /></div></p><p></p><p> <img alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKEAAAA6CAYAAADY8Dk2AAAGIklEQVR4Xu2dPXJUMQzHlYE2B+ACcIBADw0VGWjJATgAUPExwwzM0BB6OEDShoEqDemTHAAuwAFo+VQenni9kiXZ1r5lop2hydp+8k9/S7afvWz8/vuB+ASBGQlshAhnpB+PPiMQIgwhzE4gRDi7C8KAEGFoYHYCpAi3trZmNywMuDgEQoQXx9dr29MQ4dq65uIYFiK8OL5e257KItzcBLhzB+DmTYDr16eOnJwAHB0BfPoE8P37WnXu9PT0zJ6h81qKwZpzGOEUF5aEYXURXrsG8OYNADoWRYf/8IOCTKJ89Ajgyxe2z6kjqYBGHC11sP28nuY5KkdxDDo51J49zHZVB+lCLiwZe3gRIvx37wBevDgXX9kICvHxYwBBiBaB9HZ+6OjVMEhiNHLghIb2r4MIc59520OLEMW1twewu8sLMAkyCfH+/Wpq1opLW44b5MNEiClYyyAXopJDiPDcg7QIUXxXr05RUPPBcl+/Tk5jPmmE10SiKSOZM0yEOzs2BmiYkgMW9Y4uEifN98NYCg+jRYhzQBRUmgNKFmM0RKc9eOAqwnKuSDlTEnkyUBTB+/c2BikaKjhwdlM21TJD3leqnKZu7rDy+cNYNolwoiRJb/F7FG6lTj7X4TpXi4RUHe3f0NCyrDj3EvpTGW0iB60IazZzi7eaGJPItNxqfsr7ILL8X0QoibQHnLbuAitnEVJ+ySORxmZNGW4AlgOhtS2qfVv0Yo5ybTmm49xobjRp5iJcqqnBlBy/8P3M6ZiaepRTiR7h5H11Z9kUCR0XJskeTarh5ihJvKOcQDJa8cKkTGmWgWiNoFQgcGXZJEJcaOzvTxvV0uLEsEXDwdI4oAeSxqFLnHCLRssAKxs4UHPC8vkam1uZtNYbkXopPa50s1qKbFyU5DpvhUnNg6qr5Bk2q0sGNZut/R+xMKmlbnHHgYmI8ms7TM3pXXHDa7sc6kgRljBSNJVWdDkHFTQUIsUgRT/l68vaAOOyFTUv7Em9nAhXxrJJhFgJ09L29pRu0hZMepf88aN4gEEDsoRT2kp9j3+j4NVExo1iYcpCM5jC8zRdaeRgSctURCz7WrIuGeVt1NjV6kmRWmRJFJBP0bS0GnWCgIFAiNAAK4r6EAgR+nCNVg0EQoQGWFHUh0CI0IdrtGogECI0wIqiPgRChD5co1UDgRChAVYU9SEQIvThGq0aCMgivHIF4OFDgBs3pjcH+MFrnsfHAG/fAnz7Znicf1HNi3+zFXHl04zMUqEuwtu3AV6+BLh8mW7zxw+A588BDg/ZZ1KvkiQDW+pgm82v5WoGxZVP9/swvAhRgK9fS3oB+PUL4OnTqhAtAukV0tBIOMMpmvJYm+wAvxJDWVbMpEWIv7hwcMBHwLJBjIj37lVTs1Zc2nJcn4aBiyufS/dyvOROi/DzZ4Bbt2zPxDp4AZz5SEetUrTMT3CojloVzxsmwhWfrLbBXk3pYSwFc2kR4sIjLUK0/cU6eNzLUYTSsbA87VuvTy6ZPfMdk2RPLTPkIqHKaerm/V6/K59a8S32QhRhTSi1aNl6irh0Zn42sRppnW/bUQ6XRJDPF7nFW02MI05WU/7rncfSkbBFgFin494xBXjEKWJO9GKqcRYhhdja39aB2VqvmeW6peO8I5Nup0v2kgjLfnCppgZYcvzC9zOnY2rqkewbFdGklD+MZZMIHRcmmvTIRalSeD0jWgz2K16YlClNjNT/Bm4+kC2RaqUsm0SIWzQfPgBcuiT66qzAz58Ad++KWzRx5XP550g4wJ4i7Bm8Grt0ojkv1b9Zjf8r2ZMnqs3qkbftekZ9Ho3jyudEwypMKgK3bKlhO/Jru1ev+IiIEfDZM1GA5ZyvZy5Su3lX22PUbO+QIziufC69tmtmyYRI3QEG/CVW/L3q/AAD3kXG+7jCAQbJ4Nq2AzcRT6OQm9eU9STRi+mDuvY6jay48vkXQ2sETNxlEYoeigJBoI9AiLCPX9QeQCBEOABiNNFHIETYxy9qDyAQIhwAMZroI0CKsK/JqB0EbARChDZeUdqBQIjQAWo0aSMQIrTxitIOBEKEDlCjSRuBEKGNV5R2IBAidIAaTdoI/AELH9ErP3Z7OAAAAABJRU5ErkJggg==" /></p>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-71850471440560890092023-10-11T15:44:00.006+03:002023-10-11T16:53:59.612+03:00Emoji in the Browser<p><b><span style="font-size: large;">HTML</span>
</b></p>
<p>The most straightforward way. You can paste the previously chosen Emoji.<br />
</p>
<div class="highlight js-code-highlight">
<pre class="highlight html"><code><span class="nt"><p></span>🔥<span class="nt"></p></span>
</code></pre>
</div>
<p>Your other option is to use the codepoint of the Emoji and replacing <code>U+</code> with <code>&#x</code>.<br />
</p>
<div class="highlight js-code-highlight">
<pre class="highlight html"><code><span class="nt"><p></span><span class="err">&</span>#x1F525<span class="nt"></p></span>
</code></pre>
</div>
<h2>
<a class="anchor" href="https://dev.to/beumsk/how-to-add-emoji-s-in-your-website-using-html-css-or-javascript-4g6g#css" name="css">
</a>
CSS
</h2>
<p>In CSS you need to use the <code>::before</code> or <code>::after</code> pseudo-element coupled with the content property where you paste the Emoji as the value.<br />
</p>
<div class="highlight js-code-highlight">
<pre class="highlight css"><code><span class="c">/* You need an HTML element with the class 'element' */</span>
<span class="nc">.element</span><span class="nd">::before</span> <span class="p">{</span>
<span class="nl">content</span><span class="p">:</span> <span class="s1">"🔥"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre>
</div>
<p>The same way, you can use codepoint replacing <code>U+</code> with <code>\0</code>.<br />
</p>
<div class="highlight js-code-highlight">
<pre class="highlight css"><code><span class="c">/* You need an HTML element with the class 'element' */</span>
<span class="nc">.element</span><span class="nd">::before</span> <span class="p">{</span>
<span class="nl">content</span><span class="p">:</span> <span class="s1">"\01F525"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre>
</div>
<h2>
<a class="anchor" href="https://dev.to/beumsk/how-to-add-emoji-s-in-your-website-using-html-css-or-javascript-4g6g#javascript" name="javascript">
</a>
JavaScript
</h2>
<p>In JavaScript you need to specify the <code>innerHTML</code> by pasting the Emoji.<br />
</p>
<div class="highlight js-code-highlight">
<pre class="highlight javascript"><code><span class="cm">/* You need an HTML element with the class 'element' */</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">"</span><span class="s2">.element</span><span class="dl">"</span><span class="p">).</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">🔥</span><span class="dl">"</span><span class="p">;</span>
</code></pre>
</div>
<p>Similarly, you can use the String method <code>fromCodePoint</code> mixed with the codepoint value where you replace <code>U+</code> with <code>0x</code>.<br />
</p>
<div class="highlight js-code-highlight">
<pre class="highlight javascript"><code><span class="cm">/* You need an HTML element with the class 'element' */</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">"</span><span class="s2">.element</span><span class="dl">"</span><span class="p">).</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="nb">String</span><span class="p">.</span><span class="nx">fromCodePoint</span><span class="p">(</span><span class="mh">0x1F525</span><span class="p">);</span>
</code></pre>
</div>
<h2>
</h2><div aria-label="HTML" class="code-wrap code-box box active" id="html-box" role="region">
<div style="text-align: center;"><pre tabindex="0"><code class="cm-s-default" data-lang="htmlmixed" id="actual-html-code">****</code></pre></div><pre tabindex="0"><code class="cm-s-default" data-lang="css" id="actual-css-code"><span class="cm-tag"><style> </span></code></pre><pre tabindex="0"><code class="cm-s-default" data-lang="css" id="actual-css-code"><span class="cm-tag">body</span> {
<span class="cm-property">font-family</span>: <span class="cm-variable">Arial</span>, <span class="cm-atom">sans-serif</span>;
}
<span class="cm-qualifier">.css-1</span>::<span class="cm-variable-3">before</span> {
<span class="cm-property">content</span>: <span class="cm-string">"🔥"</span>;
}
<span class="cm-qualifier">.css-2</span>::<span class="cm-variable-3">before</span> {
<span class="cm-comment">/* replace U+ with \0 */</span>
<span class="cm-property">content</span>: <span class="cm-string">"\01F525"</span>;
}
<span class="cm-tag">p</span> {
}
<span class="cm-qualifier">.fire</span> {
<span class="cm-property">font-size</span>: <span class="cm-number">24px</span>;
}</code></pre><pre tabindex="0"><code class="cm-s-default" data-lang="css" id="actual-css-code"><span class="cm-tag"></style></span></code><code class="cm-s-default" data-lang="css" id="actual-css-code"> </code></pre><pre tabindex="0"><code class="cm-s-default" data-lang="css" id="actual-css-code"> </code><code class="cm-s-default" data-lang="htmlmixed" id="actual-html-code"> <span class="cm-tag cm-bracket"><</span><span class="cm-tag">h1</span><span class="cm-tag cm-bracket">></span>Emoji's in the Web<span class="cm-tag cm-bracket"></</span><span class="cm-tag">h1</span><span class="cm-tag cm-bracket">></span>
<span class="cm-tag cm-bracket"><</span><span class="cm-tag">p</span><span class="cm-tag cm-bracket">></span><span class="cm-tag cm-bracket"><</span><span class="cm-tag">span</span> <span class="cm-attribute">class</span>=<span class="cm-string">"fire html-1"</span><span class="cm-tag cm-bracket">></span>🔥<span class="cm-tag cm-bracket"></</span><span class="cm-tag">span</span><span class="cm-tag cm-bracket">></span> Insert in HTML by copy pasting<span class="cm-tag cm-bracket"></</span><span class="cm-tag">p</span><span class="cm-tag cm-bracket">></span>
<span class="cm-comment"><!-- replace U+ with &#x --></span>
<span class="cm-tag cm-bracket"><</span><span class="cm-tag">p</span><span class="cm-tag cm-bracket">></span><span class="cm-tag cm-bracket"><</span><span class="cm-tag">span</span> <span class="cm-attribute">class</span>=<span class="cm-string">"fire html-2"</span><span class="cm-tag cm-bracket">></span><span class="cm-error">&#x1F525</span><span class="cm-tag cm-bracket"></</span><span class="cm-tag">span</span><span class="cm-tag cm-bracket">></span> Insert in HTML with its codepoint (replace U+ with <span class="cm-error">&#x</span>)<span class="cm-tag cm-bracket"></</span><span class="cm-tag">p</span><span class="cm-tag cm-bracket">></span>
<span class="cm-tag cm-bracket"><</span><span class="cm-tag">p</span><span class="cm-tag cm-bracket">></span><span class="cm-tag cm-bracket"><</span><span class="cm-tag">span</span> <span class="cm-attribute">class</span>=<span class="cm-string">"fire css-1"</span><span class="cm-tag cm-bracket">></span><span class="cm-tag cm-bracket"></</span><span class="cm-tag">span</span><span class="cm-tag cm-bracket">></span> Insert in CSS by copy pasting<span class="cm-tag cm-bracket"></</span><span class="cm-tag">p</span><span class="cm-tag cm-bracket">></span>
<span class="cm-comment"><!-- replace U+ with \0 --></span>
<span class="cm-tag cm-bracket"><</span><span class="cm-tag">p</span><span class="cm-tag cm-bracket">></span><span class="cm-tag cm-bracket"><</span><span class="cm-tag">span</span> <span class="cm-attribute">class</span>=<span class="cm-string">"fire css-2"</span><span class="cm-tag cm-bracket">></span><span class="cm-tag cm-bracket"></</span><span class="cm-tag">span</span><span class="cm-tag cm-bracket">></span> Insert in CSS with its codepoint (replace U+ with \0)<span class="cm-tag cm-bracket"></</span><span class="cm-tag">p</span><span class="cm-tag cm-bracket">></span>
<span class="cm-tag cm-bracket"><</span><span class="cm-tag">p</span><span class="cm-tag cm-bracket">></span><span class="cm-tag cm-bracket"><</span><span class="cm-tag">span</span> <span class="cm-attribute">class</span>=<span class="cm-string">"fire js-1"</span><span class="cm-tag cm-bracket">></span><span class="cm-tag cm-bracket"></</span><span class="cm-tag">span</span><span class="cm-tag cm-bracket">></span> Insert in JS by copy pasting<span class="cm-tag cm-bracket"></</span><span class="cm-tag">p</span><span class="cm-tag cm-bracket">></span>
<span class="cm-comment"><!-- replace U+ with 0x --></span>
<span class="cm-tag cm-bracket"><</span><span class="cm-tag">p</span><span class="cm-tag cm-bracket">></span><span class="cm-tag cm-bracket"><</span><span class="cm-tag">span</span> <span class="cm-attribute">class</span>=<span class="cm-string">"fire js-2"</span><span class="cm-tag cm-bracket">></span><span class="cm-tag cm-bracket"></</span><span class="cm-tag">span</span><span class="cm-tag cm-bracket">></span> Insert in JS with its codepoint (replace U+ with 0x)<span class="cm-tag cm-bracket"></</span><span class="cm-tag">p</span><span class="cm-tag cm-bracket">></span>
<span class="cm-tag cm-bracket"><</span><span class="cm-tag">p</span><span class="cm-tag cm-bracket">></span><span class="cm-tag cm-bracket"><</span><span class="cm-tag">a</span> <span class="cm-attribute">href</span>=<span class="cm-string">"https://emojipedia.org/"</span> <span class="cm-attribute">target</span>=<span class="cm-string">"_blank"</span><span class="cm-tag cm-bracket">></span>Find your Emoji's<span class="cm-tag cm-bracket"></</span><span class="cm-tag">a</span><span class="cm-tag cm-bracket">></span><span class="cm-tag cm-bracket"></</span><span class="cm-tag">p</span><span class="cm-tag cm-bracket">></span></code></pre><pre tabindex="0"><code class="cm-s-default" data-lang="htmlmixed" id="actual-html-code"><span class="cm-tag cm-bracket"> </span></code></pre><pre tabindex="0"><code class="cm-s-default" data-lang="javascript" id="actual-js-code"><span class="cm-variable"><script></span></code></pre><pre tabindex="0"><code class="cm-s-default" data-lang="javascript" id="actual-js-code"><span class="cm-variable">document</span>.<span class="cm-property">querySelector</span>(<span class="cm-string">".js-1"</span>).<span class="cm-property">innerHTML</span> <span class="cm-operator">=</span> <span class="cm-string">"🔥"</span>;
<span class="cm-comment">// replace U+ with 0x</span>
<span class="cm-variable">document</span>.<span class="cm-property">querySelector</span>(<span class="cm-string">".js-2"</span>).<span class="cm-property">innerHTML</span> <span class="cm-operator">=</span> <span class="cm-variable">String</span>.<span class="cm-property">fromCodePoint</span>(<span class="cm-number">0x1F525</span>);</code><code class="cm-s-default" data-lang="css" id="actual-css-code"> </code><code class="cm-s-default" data-lang="htmlmixed" id="actual-html-code"><span class="cm-tag cm-bracket"> </span> </code></pre><pre tabindex="0"><code class="cm-s-default" data-lang="javascript" id="actual-js-code"><span class="cm-variable"></script></span></code><code class="cm-s-default" data-lang="javascript" id="actual-js-code"><span class="cm-variable"></span></code><code class="cm-s-default" data-lang="htmlmixed" id="actual-html-code"> </code></pre><pre tabindex="0"><code class="cm-s-default" data-lang="htmlmixed" id="actual-html-code">https://css-tricks.com/the-checkbox-hack/ </code></pre>
</div><h2><a class="anchor" href="https://dev.to/beumsk/how-to-add-emoji-s-in-your-website-using-html-css-or-javascript-4g6g#live-example-on-codepen" name="live-example-on-codepen"></a></h2>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-41142200721280190242023-10-02T17:35:00.005+03:002023-10-02T20:53:49.625+03:00Python Asyncio Libraries 2023<ul style="text-align: left;"><li> <a href="https://github.com/timofurrer/awesome-asyncio#web-frameworks">Web Frameworks</a><a href="https://github.com/timofurrer/awesome-asyncio#message-queues">Message Queues</a></li><li><a href="https://github.com/timofurrer/awesome-asyncio#database-drivers">Database Drivers</a></li><li><a href="https://github.com/timofurrer/awesome-asyncio#networking">Networking</a></li><li><a href="https://github.com/timofurrer/awesome-asyncio#graphql">GraphQL</a></li><li><a href="https://github.com/timofurrer/awesome-asyncio#testing">Testing</a></li><li><a href="https://github.com/timofurrer/awesome-asyncio#alternative-loops">Alternative Loops</a></li><li><a href="https://github.com/timofurrer/awesome-asyncio#misc">Misc</a></li><li><a href="https://github.com/timofurrer/awesome-asyncio#writings">Writings</a></li><li><a href="https://github.com/timofurrer/awesome-asyncio#talks">Talks</a></li><li><a href="https://github.com/timofurrer/awesome-asyncio#alternatives-to-asyncio">Alternatives to asyncio</a></li></ul><hr style="text-align: left;" />
<h2 id="user-content-web-frameworks" style="text-align: left;" tabindex="-1"><a class="heading-link" href="https://github.com/timofurrer/awesome-asyncio#web-frameworks">Web Frameworks<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h2><p style="text-align: left;"><i>Libraries to build web applications.</i></p>
<ul style="text-align: left;"><li><a href="https://github.com/tiangolo/fastapi">FastAPI</a> - A very high performance Python 3.6+ API framework based on type hints. Powered by Starlette and Pydantic.</li><li><a href="https://www.djangoproject.com/" rel="nofollow">Django</a> - An established, high-level Python web framework with a huge community and ecosystem.</li><li><a href="https://github.com/encode/starlette">Starlette</a> - A lightweight ASGI framework/toolkit for building high performance services.</li><li><a href="https://github.com/KeepSafe/aiohttp">aiohttp</a> - Http client/server for asyncio (PEP-3156).</li><li><a href="https://github.com/channelcat/sanic">sanic</a> - Python 3.5+ web server that's written to go fast.</li><li><a href="https://github.com/pallets/quart">Quart</a> - An asyncio web microframework with the same API as Flask.</li><li><a href="https://github.com/crossbario/autobahn-python">autobahn</a> - WebSocket and WAMP supporting asyncio and Twisted, for clients and servers.</li><li><a href="https://github.com/aaugustin/websockets/">websockets</a> - A library for building WebSocket servers and clients in Python with a focus on correctness and simplicity.</li><li><a href="http://www.tornadoweb.org/en/stable/" rel="nofollow">Tornado</a> - Performant web framework and asynchronous networking library.</li><li><a href="https://github.com/encode/uvicorn">uvicorn</a> - The lightning-fast ASGI server.</li></ul>
<h2 id="user-content-message-queues" style="text-align: left;" tabindex="-1"><a class="heading-link" href="https://github.com/timofurrer/awesome-asyncio#message-queues">Message Queues<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h2><p style="text-align: left;"><i>Libraries to implement applications using message queues.</i></p>
<ul style="text-align: left;"><li><a href="https://github.com/Polyconseil/aioamqp">aioamqp</a> - AMQP implementation using asyncio.</li><li><a href="https://github.com/zeromq/pyzmq">pyzmq</a> - Python bindings for ZeroMQ.</li><li><a href="https://github.com/aio-libs/aiozmq">aiozmq</a> - Alternative Asyncio integration with ZeroMQ.</li><li><a href="https://github.com/crossbario/crossbar">crossbar</a> - Crossbar.io is a networking platform for distributed and microservice applications.</li><li><a href="https://github.com/nats-io/asyncio-nats">asyncio-nats</a> - Client for the NATS messaging system.</li><li><a href="https://github.com/aio-libs/aiokafka">aiokafka</a> - Client for Apache Kafka.</li></ul>
<h2 id="user-content-database-drivers" style="text-align: left;" tabindex="-1"><a class="heading-link" href="https://github.com/timofurrer/awesome-asyncio#database-drivers">Database Drivers<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h2><p style="text-align: left;"><i>Libraries to connect to databases.</i></p>
<ul style="text-align: left;"><li><a href="https://github.com/MagicStack/asyncpg">asyncpg</a> - Fast PostgreSQL Database Client Library for Python/asyncio.</li><li><a href="https://github.com/CanopyTax/asyncpgsa">asyncpgsa</a> - Asyncpg with sqlalchemy core support.</li><li><a href="https://github.com/aio-libs/aiopg/">aiopg</a> - Library for accessing a PostgreSQL database.</li><li><a href="https://github.com/aio-libs/aiomysql">aiomysql</a> - Library for accessing a MySQL database</li><li><a href="https://github.com/aio-libs/aioodbc">aioodbc</a> - Library for accessing a ODBC databases.</li><li><a href="https://github.com/mongodb/motor">motor</a> - The async Python driver for MongoDB.</li><li><a href="https://github.com/redis/redis-py">redis-py</a> - Redis Python Client (which includes <a href="https://github.com/aio-libs/aioredis">aioreadis</a> now).</li><li><a href="https://github.com/aio-libs/aiocouchdb">aiocouchdb</a> - CouchDB client built on top of aiohttp (asyncio).</li><li><a href="https://github.com/plugaai/aioinflux">aioinflux</a> - InfluxDB client built on top of aiohttp.</li><li><a href="https://github.com/aio-libs/aioes">aioes</a> - Asyncio compatible driver for elasticsearch.</li><li><a href="https://github.com/05bit/peewee-async">peewee-async</a> - ORM implementation based on <a href="https://github.com/coleifer/peewee">peewee</a> and aiopg.</li><li><a href="https://github.com/fantix/gino">GINO</a> - is a lightweight asynchronous Python ORM based on <a href="https://www.sqlalchemy.org/" rel="nofollow">SQLAlchemy</a> core, with <a href="https://github.com/MagicStack/asyncpg">asyncpg</a> dialect.</li><li><a href="https://github.com/tortoise/tortoise-orm">Tortoise ORM</a> - native multi-backend ORM with Django-like API and easy relations management.</li><li><a href="https://github.com/encode/databases">Databases</a> - Async database access for SQLAlchemy core, with support for PostgreSQL, MySQL, and SQLite.</li><li><a href="https://github.com/RobertCraigie/prisma-client-py">Prisma Client Python</a>
- An auto-generated, fully type safe ORM powered by Pydantic and
tailored specifically for your schema - supports SQLite, PostgreSQL,
MySQL, MongoDB, MariaDB and more.</li><li><a href="https://github.com/piccolo-orm/piccolo">Piccolo</a> - An ORM / query builder which can work in async and sync modes, with a nice admin GUI, and ASGI middleware.</li><li><a href="https://beanie-odm.dev" rel="nofollow">Beanie</a> - An async MongoDB ODM built on <a href="https://github.com/mongodb/motor">motor</a> and <a href="https://pydantic-docs.helpmanual.io" rel="nofollow">Pydantic</a>.</li></ul>
<h2 id="user-content-networking" style="text-align: left;" tabindex="-1"><a class="heading-link" href="https://github.com/timofurrer/awesome-asyncio#networking">Networking<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h2><p style="text-align: left;"><i>Libraries to communicate in your network.</i></p>
<ul style="text-align: left;"><li><a href="https://github.com/ronf/asyncssh">AsyncSSH</a> - Provides an asynchronous client and server implementation of the SSHv2 protocol.</li><li><a href="https://github.com/saghul/aiodns">aiodns</a> - Simple DNS resolver for asyncio.</li><li><a href="https://github.com/stellarbit/aioping">aioping</a> - Fast asyncio implementation of ICMP (ping) protocol.</li><li><a href="https://github.com/encode/httpx">httpx</a> - asynchronous HTTP client for Python 3 with <a href="https://github.com/psf/requests">requests</a> compatible API.</li></ul>
<h2 id="user-content-graphql" style="text-align: left;" tabindex="-1"><a class="heading-link" href="https://github.com/timofurrer/awesome-asyncio#graphql">GraphQL<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h2><p style="text-align: left;"><i>Libraries to build GraphQL servers.</i></p>
<ul style="text-align: left;"><li><a href="https://ariadnegraphql.org" rel="nofollow">Ariadne</a> - Schema-first Python library for implementing GraphQL servers.</li><li><a href="https://tartiflette.io/" rel="nofollow">Tartiflette</a> - Schema-first Python 3.6+ GraphQL engine built on top of <code>libgraphqlparser</code>.</li><li><a href="https://strawberry.rocks" rel="nofollow">Strawberry</a> - Code-first Python 3 GraphQL server with Django, Flask and FastAPI/Starlette support.</li></ul>
<h2 id="user-content-testing" style="text-align: left;" tabindex="-1"><a class="heading-link" href="https://github.com/timofurrer/awesome-asyncio#testing">Testing<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h2><p style="text-align: left;"><i>Libraries to test asyncio based applications.</i></p>
<ul style="text-align: left;"><li><a href="https://github.com/nhumrich/aiomock/">aiomock</a> - A python mock library that supports async methods.</li><li><a href="https://github.com/Martiusweb/asynctest/">asynctest</a> - Enhance the standard unittest package with features for testing. asyncio libraries</li><li><a href="https://github.com/pytest-dev/pytest-asyncio">pytest-asyncio</a> - Pytest support for asyncio.</li><li><a href="https://github.com/CircleUp/aresponses">aresponses</a> - Asyncio http mocking. Similar to the <a href="https://github.com/getsentry/responses">responses</a> library used for <a href="https://github.com/requests/requests">requests</a>.</li><li><a href="https://github.com/pnuckowski/aioresponses">aioresponses</a> - Helper for mock/fake web requests in Python aiohttp package.</li></ul>
<h2 id="user-content-alternative-loops" style="text-align: left;" tabindex="-1"><a class="heading-link" href="https://github.com/timofurrer/awesome-asyncio#alternative-loops">Alternative Loops<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h2><p style="text-align: left;"><i>Alternative asyncio loop implementations.</i></p>
<ul style="text-align: left;"><li><a href="https://github.com/MagicStack/uvloop">uvloop</a> - Ultra fast implementation of asyncio event loop on top of libuv.</li></ul>
<h2 id="user-content-misc" style="text-align: left;" tabindex="-1"><a class="heading-link" href="https://github.com/timofurrer/awesome-asyncio#misc">Misc<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h2><p style="text-align: left;"><i>Other awesome asyncio libraries.</i></p>
<ul style="text-align: left;"><li><a href="https://github.com/zh217/aiochan">aiochan</a> - CSP-style concurrency with channels, select and multiprocessing on top of asyncio.</li><li><a href="https://github.com/argaen/aiocache">aiocache</a> - Cache manager for different backends.</li><li><a href="https://github.com/Tinche/aiofiles/">aiofiles</a> - File support for asyncio.</li><li><a href="https://github.com/alexdelorenzo/aiopath">aiopath</a> - Asynchronous <code>pathlib</code> for asyncio.</li><li><a href="https://github.com/qntln/aiodebug">aiodebug</a> - A tiny library for monitoring and testing asyncio programs.</li><li><a href="https://github.com/cjrh/aiorun">aiorun</a> - A <code>run()</code> function that handles all the usual boilerplate for startup and graceful shutdown.</li><li><a href="https://github.com/artfwo/aiosc">aiosc</a> - Lightweight Open Sound Control implementation.</li><li><a href="https://github.com/changyuheng/aioserial">aioserial</a> - A drop-in replacement of <a href="https://github.com/pyserial/pyserial">pySerial</a>.</li><li><a href="https://github.com/aio-libs/aiozipkin">aiozipkin</a> - Distributed tracing instrumentation for asyncio with zipkin</li><li><a href="https://github.com/django/asgiref">asgiref</a> - Backend utils for ASGI to WSGI integration, includes sync_to_async and async_to_sync function wrappers.</li><li><a href="https://github.com/ryananguiano/async_property">async_property</a> - Python decorator for async properties.</li><li><a href="https://github.com/howie6879/ruia">ruia</a> - An async web scraping micro-framework based on asyncio.</li><li><a href="https://github.com/tomplus/kubernetes_asyncio">kubernetes_asyncio</a> - Asynchronous client library for Kubernetes.</li><li><a href="https://github.com/aiokitchen/aiomisc">aiomisc</a> - Miscellaneous utils for <code>asyncio</code>.</li><li><a href="https://taskiq-python.github.io/" rel="nofollow">taskiq</a> - Asynchronous distributed task manager (like celery, but async).</li></ul>
<h2 id="user-content-writings" style="text-align: left;" tabindex="-1"><a class="heading-link" href="https://github.com/timofurrer/awesome-asyncio#writings">Writings<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h2><p style="text-align: left;"><i>Documentation, blog posts, and other awesome writing about asyncio.</i></p>
<ul style="text-align: left;"><li><a href="https://docs.python.org/3/library/asyncio.html" rel="nofollow">Official asyncio documentation</a> - Asynchronous I/O, event loop, coroutines and tasks.</li><li><a href="http://masnun.com/2015/11/13/python-generators-coroutines-native-coroutines-and-async-await.html" rel="nofollow">Short well-written intro to asyncio</a> - Generators, Coroutines, Native Coroutines and async/await.</li><li><a href="https://hackernoon.com/asyncio-for-the-working-python-developer-5c468e6e2e8e" rel="nofollow">AsyncIO for the Working Python Developer</a> - A gentle introduction to asynchronous programming from basic examples working up to URL fetching.</li><li><a href="https://pawelmhm.github.io/asyncio/python/aiohttp/2016/04/22/asyncio-aiohttp.html" rel="nofollow">Test limits of Python aiohttp</a> - Making 1 million requests with python-aiohttp.</li><li><a href="https://asgi.readthedocs.io/en/latest/" rel="nofollow">ASGI (Asynchronous Server Gateway Interface)</a>
- A spiritual successor to WSGI, intended to provide a standard
interface between async-capable Python web servers, frameworks, and
applications.</li><li><a href="https://hackernoon.com/a-simple-introduction-to-pythons-asyncio-595d9c9ecf8c" rel="nofollow">First Principles Introduction to Asyncio</a> - A no-buzzword first principles introduction to the internal workings of asyncio.</li><li><a href="https://testdriven.io/blog/fastapi-crud/" rel="nofollow">Developing and Testing an Asynchronous API with FastAPI and Pytest</a> - This tutorial looks at how to develop and test an asynchronous API with FastAPI using Test-Driven Development (TDD).</li><li><a href="https://www.manning.com/books/python-concurrency-with-asyncio" rel="nofollow">Python Concurrency with asyncio</a> - Learn how to speed up slow Python code with concurrent programming and the cutting-edge asyncio library.</li></ul>
<h2 id="user-content-talks" style="text-align: left;" tabindex="-1"><a class="heading-link" href="https://github.com/timofurrer/awesome-asyncio#talks">Talks<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h2><p style="text-align: left;"><i>Recordings of awesome talks about asyncio.</i></p>
<ul style="text-align: left;"><li><a href="https://youtu.be/ZzfHjytDceU" rel="nofollow">Topics of Interest (Python Asyncio)</a> | <a href="https://youtu.be/lYe8W04ERnY" rel="nofollow">screencast</a> | <a href="https://speakerdeck.com/dabeaz/topics-of-interest-async" rel="nofollow">slides</a> - PyCon Brasil 2015 keynote (David Beazley).</li><li><a href="https://www.youtube.com/playlist?list=PLpEcQSRWP2IjVRlTUptdD05kG-UkJynQT" rel="nofollow">Python Asynchronous I/O Walkthrough</a> - 8-part code walkthrough (Philip Guo).</li><li><a href="https://www.youtube.com/watch?v=m28fiN9y_r8&t=132s" rel="nofollow">Async/await in Python 3.5 and why it is awesome</a> - EuroPython 2016 (Yury Selivanov).</li><li><a href="https://www.youtube.com/watch?v=E-1Y4kSsAFc" rel="nofollow">Fear and Awaiting in Async: A Savage Journey to the Heart of the Coroutine Dream</a> | <a href="https://www.youtube.com/watch?v=Bm96RqNGbGo" rel="nofollow">screencast</a> - PyOhio 2016 keynote (David Beazley).</li><li><a href="https://www.youtube.com/watch?v=iG6fr81xHKA" rel="nofollow">Asynchronous Python for the Complete Beginner</a> | <a href="https://speakerdeck.com/pycon2017/miguel-grinberg-asynchronous-python-for-the-complete-beginner" rel="nofollow">slides</a> - PyCon 2017 (Miguel Grinberg).</li><li><a href="https://www.youtube.com/watch?v=F19R_M4Nay4" rel="nofollow">Demystifying Python's Async and Await Keywords</a> - JetBrains TV 2020 (Michael Kennedy)</li></ul>
<h2 id="user-content-alternatives-to-asyncio" style="text-align: left;" tabindex="-1"><a class="heading-link" href="https://github.com/timofurrer/awesome-asyncio#alternatives-to-asyncio">Alternatives to asyncio<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h2><p style="text-align: left;"><i>Alternative approaches to async programming in Python, some of which attempt to support some compatibility with <code>asyncio</code>, others are not compatible at all.</i></p>
<ul style="text-align: left;"><li><a href="https://github.com/dabeaz/curio">curio</a> - The coroutine concurrency library.
<ul><li><a data-hovercard-type="issue" data-hovercard-url="/dabeaz/curio/issues/190/hovercard" href="https://github.com/dabeaz/curio/issues/190">Curio-Asyncio Bridge</a> - basic curio -> asyncio coroutine bridge.</li></ul>
</li><li><a href="https://github.com/python-trio/trio">trio</a> - Pythonic async I/O for humans and snake people.
<ul><li><a href="https://github.com/python-trio/trio-asyncio">trio-asyncio</a> - re-implementation of the asyncio mainloop on top of Trio.</li></ul>
</li><li><a href="https://github.com/agronholm/anyio">AnyIO</a> - High level asynchronous concurrency and networking framework that works on top of either trio or asyncio.</li></ul><p>Source: https://github.com/timofurrer/awesome-asyncio </p><p style="text-align: center;">*****</p><p>A list of libraries for AsyncIO is available on PyPI with <a href="https://pypi.python.org/pypi?:action=browse&show=all&c=633" rel="nofollow">Framework::AsyncIO</a> classifier.</p>
<h1 id="user-content-alternative-event-loop-implementations"><a class="heading-link" href="https://github.com/python/asyncio/wiki/ThirdParty#alternative-event-loop-implementations">Alternative event loop implementations<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h1><ul><li>
<a href="https://github.com/magicstack/uvloop">uvloop</a>: Ultra fast implementation of asyncio event loop on top of libuv. Read more about uvloop <a href="http://magic.io/blog/uvloop-blazing-fast-python-networking/" rel="nofollow">here</a>.</li><li>
<a href="https://github.com/PyO3/tokio">async-tokio</a>: Asyncio event loop implementation, written in Rust language</li></ul>
<h1 id="user-content-libraries"><a class="heading-link" href="https://github.com/python/asyncio/wiki/ThirdParty#libraries">Libraries<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h1><ul><li>
<a href="https://github.com/Tinche/aiofiles/">aiofiles</a>: File support for asyncio</li><li>
<a href="https://github.com/argaen/aiocache">aiocache</a>: Caching for asyncio with multiple backends (framework agnostic)</li><li>
<a href="https://pypi.python.org/pypi/aiorwlock" rel="nofollow">aiorwlock</a>: Read write lock for asyncio</li><li>
<a href="https://pypi.python.org/pypi/aioutils" rel="nofollow">aioutils</a>: Python3 Asyncio Utils, Group (like gevent.pool.Group), Pool (like gevent.pool.Pool), Bag and OrderedBag</li><li>
<a href="https://github.com/vkryachko/tasklocals">tasklocals</a>: Task-local variables</li><li>
<a href="https://github.com/aio-libs/janus">janus</a>: Thread-safe asyncio-aware queue</li><li>
<a href="https://pypi.python.org/pypi/asyncio_extras" rel="nofollow">asyncio_extras</a>: asynchronous generator/context manager support, thread pool integration, async file operations and more</li><li>
<a href="https://github.com/h2non/paco">paco</a>: Small utility library for coroutine-driven asynchronous programming</li><li>
<a href="https://github.com/vxgmichel/aioconsole">aioconsole</a>: Asynchronous console and interfaces for asyncio</li><li>
<a href="https://github.com/vxgmichel/aiostream">aiostream</a>: Generator-based operators for asynchronous iteration</li></ul>
<h2 id="user-content-unit-testing"><a class="heading-link" href="https://github.com/python/asyncio/wiki/ThirdParty#unit-testing">Unit testing<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h2><ul><li>
<a href="https://github.com/Martiusweb/asynctest/">asynctest</a>: Enhance the standard unittest package for testing asyncio libraries</li><li>
<a href="https://github.com/pytest-dev/pytest-asyncio">pytest-asyncio</a>: Pytest support for asyncio</li></ul>
<h1 id="user-content-protocols-implementations"><a class="heading-link" href="https://github.com/python/asyncio/wiki/ThirdParty#protocols-implementations">Protocols implementations<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h1><h2 id="user-content-clients"><a class="heading-link" href="https://github.com/python/asyncio/wiki/ThirdParty#clients">Clients<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h2><ul><li>
<strong>AMQP</strong>:
<ul><li>
<a href="https://github.com/Polyconseil/aioamqp">aioamqp</a>: AMQP implementation using asyncio (Used by RabbitMQ)</li><li>
<a href="https://github.com/M-o-a-T/qbroker">QBroker</a>: easy-to-use library based on aioamqp, for pub/sub and RPC</li></ul>
</li><li>
<strong>AMI</strong>: <a href="https://panoramisk.readthedocs.org/" rel="nofollow">panoramisk</a>, a library to play with Asterisk's protocols: AMI and FastAGI</li><li>
<strong>Cassandra</strong>: <a href="https://github.com/wikibusiness/aiocassandra">aiocassandra</a>, Simple threaded cassandra wrapper for asyncio</li><li>
<strong>CouchDB</strong>: <a href="http://aiocouchdb.readthedocs.org" rel="nofollow">aiocouchdb</a>, CouchDB client</li><li>
<strong>DNS</strong>: <a href="https://pypi.python.org/pypi/aiodns" rel="nofollow">aiodns</a>: Async DNS resolver</li><li>
<strong>ElasticSearch</strong>:
<ul><li>
<a href="http://aioes.readthedocs.org/" rel="nofollow">aioes</a>: ElasticSearch client library</li><li>
<a href="https://github.com/elastic/elasticsearch-py-async">elasticsearch-py-async</a>: aiohttp transport for official elasticsearch-py driver</li><li>
<a href="https://github.com/wikibusiness/aioelasticsearch">aioelasticsearch</a>: aiohttp transport for elasticsearch-py with additional asynchronous interface</li></ul>
</li><li>
<strong>Etcd</strong>: <a href="https://github.com/lisael/aioetcd">aioetcd</a>: Coroutine-based etcd client</li><li>
<strong>Google Hangouts</strong>: <a href="https://github.com/tdryer/hangups">hangups</a>: Client for Google Hangouts</li><li>
<strong>HTTP</strong>: <a href="http://aiohttp.readthedocs.org/en/latest/client.html" rel="nofollow">aiohttp.requests</a>: http client with Requests-like API.</li><li>
<strong>IRC</strong>:
<ul><li>
<a href="https://irc3.readthedocs.org/" rel="nofollow">irc3</a>, plugable irc client library based on python's asyncio</li><li>
<a href="https://github.com/numberoverzero/bottom">bottom</a>, asyncio-based rfc2812-compliant IRC Client</li></ul>
</li><li>
<strong>Kafka</strong>: <a href="https://github.com/aio-libs/aiokafka">aiokafka</a>: Full featured Kafka client for Kafka 9.0.0+</li><li>
<strong>memcached</strong>: <a href="https://github.com/fafhrd91/aiomemcache">aiomemcache</a>, minimal memcached client</li><li>
<strong>MongoDB</strong>:
<ul><li>
<a href="https://motor.readthedocs.org/" rel="nofollow">Motor</a>, official async MongoDB driver</li><li>
<a href="https://bitbucket.org/mrdon/asyncio-mongo" rel="nofollow">asyncio-mongo</a>, MongoDB driver (ported from Twisted)</li></ul>
</li><li>
<strong>MPD</strong>: <a href="https://github.com/zzzsochi/aiompd">aiompd</a>, Music Player Daemon client for AsyncIO</li><li>
<strong>MySQL</strong>: <a href="https://github.com/aio-libs/aiomysql">aiomysql</a>, MySQL driver</li><li>
<strong>ODBC</strong>: <a href="https://github.com/aio-libs/aioodbc">aioodbc</a>, ODBC client on top of pyodbc, works only with python 3.5+</li><li>
<strong>PostgreSQL</strong>:
<ul><li>
<a href="http://aiopg.readthedocs.org/" rel="nofollow">aiopg</a>, PostgreSQL client library built on top of psycopg2</li><li>
<a href="https://github.com/realazthat/aiopg8000">aiopg8000</a>, A Pure-Python PostgreSQL driver for AsyncIO</li><li>
<a href="https://github.com/MagicStack/asyncpg">asyncpg</a>, A fast PostgreSQL Database Client Library for Python/asyncio</li></ul>
</li><li>
<strong>Prometheus</strong>: <a href="https://prometheus-async.readthedocs.io/en/stable/" rel="nofollow">prometheus_async</a> adds support for asynchronous frameworks to the official Python client for the Prometheus metrics and monitoring system.</li><li>
<strong>PySerial</strong>: <a href="https://github.com/m-labs/asyncserial">asyncserial</a>: asyncio support for pySerial</li><li>
<strong>Redis</strong>:
<ul><li>
<a href="http://asyncio-redis.readthedocs.org/" rel="nofollow">asyncio-redis</a>, Redis client with pubsub support</li><li>
<a href="http://aioredis.readthedocs.org/" rel="nofollow">aioredis</a>, Yet another Redis client</li></ul>
</li><li>
<strong>Riak</strong>: <a href="https://github.com/rambler-digital-solutions/aioriak">aioriak</a>: Python asyncio client for Riak</li><li>
<strong>Slack</strong> <a href="https://github.com/wikibusiness/aioslacker">aioslacker</a>: slacker wrapper for asyncio</li><li>
<strong>SIP</strong>: <a href="https://github.com/Eyepea/aiosip">aiosip</a>: SIP support for AsyncIO</li><li>
<strong>Socks</strong>: <a href="https://github.com/nibrag/aiosocks">aiosocks</a>: SOCKS proxy client for asyncio and aiohttp</li><li>
<strong>SSH</strong>: <a href="https://github.com/ronf/asyncssh">AsyncSSH</a>: SSH client and server implementation</li><li>
<strong>WebSockets</strong>: <a href="http://aiohttp.readthedocs.org/en/latest/client_websockets.html" rel="nofollow">aiohttp.ws_connect</a>: WebSockets client</li><li>
<strong>XMPP (Jabber)</strong>:
<ul><li>
<a href="http://git.poez.io/slixmpp" rel="nofollow">slixmpp</a>, SleekXMPP (XMPP Library) fork using asyncio, for poezio,</li><li>
<a href="https://github.com/horazont/aioxmpp">aioxmpp</a>, from scratch XMPP library for asyncio (alpha)</li></ul>
</li><li>
<strong>Zipkin</strong>: <a href="https://github.com/aio-libs/aiozipkin">aiozipkin</a>: Distributed tracing instrumentation for asyncio with zipkin</li></ul>
<h2 id="user-content-servers"><a class="heading-link" href="https://github.com/python/asyncio/wiki/ThirdParty#servers">Servers<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h2><ul><li>
<strong>FastAGI</strong>: <a href="https://panoramisk.readthedocs.org/" rel="nofollow">panoramisk</a>, a library to play with Asterisk's protocols: AMI and FastAGI</li><li>
<strong>IRC</strong>: <a href="https://github.com/gawel/irc3/tree/master/irc3d">irc3d</a>, irc server library based on irc3</li><li>
<strong>HTTP</strong>: <a href="https://github.com/KeepSafe/aiohttp">aiohttp</a>: http client and server infrastructure for asyncio</li><li>
<strong>SSH</strong>: <a href="https://github.com/ronf/asyncssh">AsyncSSH</a>: SSH client and server implementation</li><li>
<strong>SMTP/LMTP</strong>: <a href="http://aiosmtpd.readthedocs.org/en/latest/" rel="nofollow">aiosmtpd</a>: Server implementations and testing frameworks for Simple Mail Transport Protocol and Local Mail Transport Protocol.</li></ul>
<h1 id="user-content-web-frameworks"><a class="heading-link" href="https://github.com/python/asyncio/wiki/ThirdParty#web-frameworks">Web Frameworks<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h1><h2 id="user-content-for-classical-http11-protocol"><a class="heading-link" href="https://github.com/python/asyncio/wiki/ThirdParty#for-classical-http11-protocol">For classical HTTP/1.1 protocol<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h2><p>Looking for WSGI? Read this thread: <a href="https://groups.google.com/forum/#!topic/python-tulip/Gs3bZ2AbS9o" rel="nofollow">WSGI implementation compatible with asyncio?</a>.</p>
<ul><li>
<a href="http://aiohttp.readthedocs.org/en/latest/web.html" rel="nofollow">aiohttp.web</a>: a Flask-like API to build quickly HTTP applications, made by the creators of <a href="https://github.com/KeepSafe/aiohttp">aiohttp</a>
</li><li>
<a href="https://pypi.python.org/pypi/aiopyramid" rel="nofollow">aiopyramid</a>: Tools for running <a href="https://pypi.python.org/pypi/pyramid" rel="nofollow">pyramid</a> using asyncio</li><li>
<a href="https://github.com/zzzsochi/aiotraversal">aiotraversal</a>: Web framework for big complicated applications based on aiohttp</li><li>
<a href="https://github.com/gawel/aiowsgi">aiowsgi</a>: minimalist wsgi server using asyncio</li><li>
<a href="https://github.com/pyGrowler/Growler">Growler</a>: A web framework built on top of aiohttp</li><li>
<a href="https://pypi.python.org/pypi/interest" rel="nofollow">interest</a>: event-driven web framework on top of aiohttp/asyncio</li><li>
<a href="https://github.com/klen/muffin">muffin</a>: A web framework based on Asyncio stack (early alpha)</li><li>
<a href="https://github.com/avelino/nacho">nacho</a>: web framework</li><li>
<a href="http://pythonhosted.org/pulsar/" rel="nofollow">Pulsar</a>:
Event driven concurrent framework for python. With pulsar you can write
asynchronous servers performing one or several activities in different
threads and/or processes.</li><li>
<a href="https://github.com/mind1master/rainfall">rainfall</a>: another web framework</li><li>
<a href="https://github.com/channelcat/sanic">sanic</a>: A Flask-like Python 3.5+ web server that's written to go fast.</li><li>
<a href="https://github.com/vkryachko/Vase">Vase</a>: web framework</li></ul>
<h2 id="user-content-for-websockets"><a class="heading-link" href="https://github.com/python/asyncio/wiki/ThirdParty#for-websockets">For WebSockets<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h2><ul><li>
<a href="http://aiohttp.readthedocs.org/en/latest/web.html" rel="nofollow">aiohttp.web</a>: a Flask-like API to build quickly HTTP applications, made by the creators of <a href="https://github.com/KeepSafe/aiohttp">aiohttp</a>.</li><li>
<a href="https://github.com/tavendo/AutobahnPython">AutobahnPython</a>: WebSocket and WAMP framework</li><li>
<a href="https://github.com/aaugustin/websockets">websockets</a>: Websockets library</li><li>
<a href="https://github.com/Lawouach/WebSocket-for-Python">WebSocket-for-Python</a>: another websocket library</li></ul>
<h1 id="user-content-orms"><a class="heading-link" href="https://github.com/python/asyncio/wiki/ThirdParty#orms">ORMs<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h1><ul><li>
<a href="http://aiopg.readthedocs.org/en/stable/sa.html" rel="nofollow">aiopg.sa</a>: support for SQLAlchemy functional SQL layer, based on aiopg</li><li>
<a href="http://aiomysql.readthedocs.org/en/latest/sa.html" rel="nofollow">aiomysql.sa</a>: support for SQLAlchemy functional SQL layer, based on aiomysql</li><li>
<a href="https://peewee.readthedocs.org/" rel="nofollow">peewee</a>: <a href="http://peewee-async.readthedocs.org/en/latest/" rel="nofollow">peewee-async</a>, library providing asynchronous interface powered by asyncio for peewee ORM.</li><li>
<a href="https://github.com/fantix/gino">GINO</a>: lightweight ORM based on asyncpg and SQLAlchemy core</li></ul>
<h1 id="user-content-integration-with-other-applications"><a class="heading-link" href="https://github.com/python/asyncio/wiki/ThirdParty#integration-with-other-applications">Integration with other applications<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h1><ul><li>
<a href="https://pypi.python.org/pypi/api_hour" rel="nofollow">API-Hour</a>:
Transform easily your AsyncIO server source code (HTTP, SSH, ...) to be
multiprocess: it will help to improve the efficency on multi-CPU
servers.</li><li>
<a href="http://www.gunicorn.org/" rel="nofollow">Gunicorn</a>: Gunicorn has gaiohttp worker built on top of aiohttp library</li></ul>
<h1 id="user-content-applications-built-with-asyncio"><a class="heading-link" href="https://github.com/python/asyncio/wiki/ThirdParty#applications-built-with-asyncio">Applications built with AsyncIO<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h1><ul><li>
<a href="https://github.com/cr0hn/ktcal2">ktcal2</a>: SSH brute forcer tool and library, using AsyncIO of Python 3.4</li></ul>
<h1 id="user-content-run-asyncio-on-top-of"><a class="heading-link" href="https://github.com/python/asyncio/wiki/ThirdParty#run-asyncio-on-top-of">Run asyncio on top of<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h1><ul><li>eventlet: <a href="http://aioeventlet.readthedocs.org/" rel="nofollow">aioeventlet</a>, asyncio API implemented on top of eventlet</li></ul>
<h1 id="user-content-adapters-for-other-event-loops"><a class="heading-link" href="https://github.com/python/asyncio/wiki/ThirdParty#adapters-for-other-event-loops">Adapters for other event loops<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h1><p>Some people have already written adapters for integrating asyncio with other async I/O frameworks.</p>
<ul><li>
<a href="http://eventlet.net/" rel="nofollow">eventlet</a>: <a href="https://github.com/1st1/greenio">greenio</a>, Greenlets support for asyncio (PEP 3156)</li><li>
<a href="http://www.gevent.org/" rel="nofollow">gevent</a>: <a href="https://github.com/decentfox/tulipcore">tulipcore</a>, run gevent code on top of asyncio, alternative gevent core loop</li><li>GLib: <a href="https://github.com/nathan-hoad/gbulb">gbulb</a>, event loop based on GLib</li><li>
<a href="https://github.com/libuv/libuv">libuv</a>: <a href="https://github.com/saghul/aiouv">aiouv</a>, an event loop implementation for asyncio based on <a href="https://pyuv.readthedocs.org/" rel="nofollow">pyuv</a>
</li><li>Qt: <a href="https://github.com/harvimt/quamash">Quamash</a>, implementation of the PEP 3156 Event-Loop with Qt.</li><li>
<a href="https://github.com/tornadoweb/tornado">Tornado</a> has <a href="https://groups.google.com/forum/#!topic/python-tulip/hg0HzhoPuFE" rel="nofollow">experimental asyncio support</a> built right into it.</li><li>
<a href="http://zeromq.org/" rel="nofollow">ZeroMQ</a>:
<ul><li>
<a href="http://aiozmq.readthedocs.org/" rel="nofollow">aiozmq</a>, ZeroMQ integration with asyncio</li><li>
<a href="https://github.com/takluyver/Zantedeschia">Zantedeschia</a>, experimental alternative integration between asyncio and ZeroMQ sockets.</li></ul>
</li></ul>
<h1 id="user-content-misc"><a class="heading-link" href="https://github.com/python/asyncio/wiki/ThirdParty#misc">Misc<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h1><ul><li>
<a href="https://github.com/klen/aioauth-client">aioauth-client</a>: OAuth1/2 support (authorization, resource's loading)</li><li>
<a href="https://github.com/gawel/aiocron/">aiocron</a>: Crontabs for asyncio</li><li>
<a href="http://stefan.sofa-rockers.org/2015/02/13/aiomas/" rel="nofollow">aiomas</a>: A library for multi-agent systems and RPC based on asyncio</li><li>
<a href="https://bitbucket.org/haypo/aiotest/" rel="nofollow">aiotest</a>: test suite to validate an implementation of the asyncio API</li><li>
<a href="https://github.com/dano/aioprocessing">aioprocessing</a>: A Python 3.3+ library that integrates the multiprocessing module with asyncio</li><li>
<a href="https://github.com/akloster/blender-asyncio">blender-asyncio</a>: Asyncio Bridge for Blender Python API</li><li>
<a href="https://github.com/tecki/ipython-yf">ipython-yf</a>: An ipython extension to make it asyncio compatible</li><li>
<a href="https://github.com/jettify/aiogearman">aiogearman</a>: asyncio <a href="http://gearman.org/" rel="nofollow">gearman</a>
support. Gearman provides a generic application framework to farm out
work to other machines or processes that are better suited to do the
work.</li><li>
<a href="https://github.com/sardok/aiogear">aiogear</a>: Yet another gearman protocol implemented in asyncio.</li><li>Serial port using the serial module, see <a href="https://stackoverflow.com/questions/21666106/using-serial-port-in-python3-asyncio" rel="nofollow">using serial port in python3 asyncio</a> at Stackoverflow, serial.Serial can be registered with loop.add_reader().</li><li>
<a href="https://github.com/wikibusiness/async_lru">async_lru</a>: port of functools.lru_cache to asyncio</li><li>
<a href="https://github.com/NikolaiT/GoogleScraper">GoogleScraper</a>: A
Python module to scrape several search engines (like Google, Yandex,
Bing, Duckduckgo, Baidu and others) by using proxies (socks4/5, http
proxy) and with many different IP's.</li><li>
<a href="https://github.com/cr0hn/aiotasks">aiotasks</a>: A Celery like task manager that distributes Asyncio coroutines.</li></ul>
<h1 id="user-content-filesystem"><a class="heading-link" href="https://github.com/python/asyncio/wiki/ThirdParty#filesystem">Filesystem<svg aria-hidden="true" class="octicon octicon-link" height="16" viewbox="0 0 16 16" width="16"></svg></a></h1><p>asyncio does <strong>not</strong> support asynchronous operations on the filesystem. Even if files are opened with O_NONBLOCK, read and write will block.</p>
<p>Read <a href="http://blog.libtorrent.org/2012/10/asynchronous-disk-io/" rel="nofollow">asynchronous disk I/O</a> (October 2012 by arvid).</p>
<p>The Linux kernel provides asynchronous operations on the filesystem
(aio), but it requires a library and it doesn't scale with many
concurrent operations. See <a href="http://lse.sourceforge.net/io/aio.html" rel="nofollow">aio</a>.</p>
<p>The GNU C library (glibc) implements the POSIX aio interface, but it is implemented with threads. See <a href="http://man7.org/linux/man-pages/man7/aio.7.html" rel="nofollow">aio(7) manual page</a>.</p>
<p>Recent discussion on the Linux Kernel: <a href="http://lwn.net/Articles/612483/" rel="nofollow">Non-blocking buffered file read operations</a> (September 2014).</p>
<p>For now, the workaround is to use <a href="https://github.com/Tinche/aiofiles/">aiofiles</a> that uses threads to handle files.</p><p></p>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-12921802594216849332023-10-02T12:21:00.004+03:002023-10-02T12:23:54.761+03:00Python Convert TSV to TMX<p>Given the tsv (tab delimited file) file data.csv with this content:<br /></p><p>English\tRomanian<br />Hello my name is John.\tSalut, numele meu e John.<br />Today is Monday.\tAzi e luni.<br /></p><p>import pandas as pd<br />import datetime<br /><br />def tsv_t_tmx(myfile='data.csv', source_lang='en', target_lang='ro', separator='\t'):<br /> now = datetime.datetime.now()<br /> d2 = now.strftime("%Y-%m-%d %H:%M:%S")<br /> df = pd.read_csv(myfile, sep=separator)<br /> f = open("demofile2.xml", "w", encoding="UTF-8")<br /><br /> f.write('''<?xml version="1.0" encoding="UTF-8" ?><br /> <tmx version="1.4">''')<br /> f.write(f'''<header creationdate="{d2}"<br /> srclang= "{source_lang}"<br /> adminlang="en"<br /> o-tmf="unknown"<br /> segtype="sentence"<br /> creationtool="Python"<br /> creationtoolversion="unknown"<br /> datatype="PlainText" /><br /> <body>\n''')<br /><br /> for index, row in df.iterrows():<br /> eng = row['English']<br /> rom = row['Romanian']<br /> <br /> f.write(f'''<br /> <tu><br /> <tuv xml:lang="{source_lang}"><br /> <seg>{eng}</seg><br /> </tuv><br /> <tuv xml:lang="{target_lang}"><br /> <seg>{rom}</seg><br /> </tuv><br /> </tu>''')<br /><br /> f.write('''<br /> </body><br /> </tmx>''')<br /><br /> f.close() <br /> base_file = "demofile2.xml"<br /> name, ext = base_file.split('.')<br /> new_file = '{}.{}'.format(name, 'tmx')<br /><br /> with open(base_file , 'r') as f1:<br /> with open(new_file, 'w') as f2:<br /> f2.write(f1.read()) <br /><br />if __name__ == "__main__":<br /> tsv_t_tmx() </p><p style="text-align: center;">*****<br /></p><p>TMX model:</p><p><tmx version="1.4"><header creationtool="" creationtoolversion="" segtype="phrase" o-tmf="" adminlang="en" srclang="en" datatype="PlainText" o-encoding="UTF-8" /><body><tu><tuv xml:lang="en"><seg /></tuv></tu><tu><tuv xml:lang="en"><seg /></tuv></tu><tu><tuv xml:lang="en"><seg /></tuv></tu></body></tmx></p><p style="text-align: center;">*****<br /></p><p><?xml version="1.0" encoding="UTF-8" ?><br /> <tmx version="1.4"><header creationdate="2023-03-16 20:30:30"<br /> srclang= "en"<br /> adminlang="en"<br /> o-tmf="unknown"<br /> segtype="sentence"<br /> creationtool="Python"<br /> creationtoolversion="3.11"<br /> datatype="PlainText" /><br /> <body><br /><br /> <tu><br /> <tuv xml:lang="en"><br /> <seg>Hello my name is John.</seg><br /> </tuv><br /> <tuv xml:lang="ro"><br /> <seg>Salut, numele meu e John.</seg><br /> </tuv><br /> </tu><br /> <tu><br /> <tuv xml:lang="en"><br /> <seg>Today is Monday.</seg><br /> </tuv><br /> <tuv xml:lang="ro"><br /> <seg>Azi e luni.</seg><br /> </tuv><br /> </tu><br /> </body><br /> </tmx><br /></p>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-59889384189002755312023-09-29T09:33:00.002+03:002023-09-29T09:33:21.559+03:00Python - Append item to list N times<p>For immutable data types:</p>
<pre class="lang-py s-code-block"><code class="hljs language-python"></code><code class="hljs language-python">l = []
x = <span class="hljs-number">0</span>
l.extend([x]*<span class="hljs-number">100</span>)</code></pre><pre class="lang-py s-code-block"><code class="hljs language-python">l = [<span class="hljs-number">0</span>] * <span class="hljs-number">100</span>
<span class="hljs-comment"># [0, 0, 0, 0, 0, ...]</span>
l = [<span class="hljs-string">'foo'</span>] * <span class="hljs-number">100</span>
<span class="hljs-comment"># ['foo', 'foo', 'foo', 'foo', ...]</span>
</code></pre>
<p>For values that are stored by reference and you may wish to modify later (like sub-lists, or dicts):</p>
<pre class="lang-py s-code-block"><code class="hljs language-python">l = [{} <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">100</span>)] </code></pre><pre class="lang-py s-code-block"><code class="hljs language-python">l = [x <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">10</span>0)]</code></pre><pre class="lang-py s-code-block">If you want to add to an existing list, you can use the <code>extend()</code> method of that list</pre><pre class="lang-py s-code-block">(in conjunction with the generation of a list):</pre><pre class="lang-py s-code-block"><code class="hljs language-python">a = [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>]
b = [<span class="hljs-number">4</span>,<span class="hljs-number">5</span>,<span class="hljs-number">6</span>]
a.extend(b)
<span class="hljs-comment"># a is now [1,2,3,4,5,6]</span></code></pre><pre class="lang-py s-code-block"><code class="hljs language-python">l.extend([x <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">100</span>)])</code></pre>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-44659555383754467942023-09-27T09:43:00.005+03:002023-09-27T09:45:27.346+03:00AI Generated Add Text from About Page - AIDA Framework - writesonic.com<p>Attention: Are you in need of top-quality translation services? Look no further! Introducing Leon Tiberiu Cristian, a highly skilled translator and interpreter specializing in German, English, and Romanian. With a passion for translation practice and technology, Leon is dedicated to delivering exceptional results for all your language needs.<br /><br />Translation can be a complex process, but with Leon's expertise, you can rest assured that your documents will be accurately and professionally translated. Whether you require translation services from or into English, German, French, Romanian, or any other international languages, Leon has got you covered.<br /><br />But what sets Leon apart from other translators? He stays up-to-date with the latest translation applications and utilizes advanced translation memory tools for a computer-aided translation process. This not only ensures efficiency but also guarantees consistent and accurate translations. Leon also employs quality assurance tools and terminology management tools to ensure the highest level of accuracy and precision.<br /><br />By using translation applications, known as CAT tools, Leon is able to streamline the translation process, saving you time and money. These tools enable him to efficiently handle large volumes of text, maintain consistency, and deliver translations of the highest quality.<br /><br />Why settle for mediocre translations when you can have exceptional ones? With Leon Tiberiu Cristian, you can expect nothing but the best. Don't miss out on the opportunity to work with a translator who is committed to excellence. Contact Leon today to discuss your translation needs and experience the difference firsthand.<br /><br />Remember, when it comes to translation services, attention to detail, expertise, and the latest technology matter. Choose Leon Tiberiu Cristian for all your translation needs and elevate your communication to a whole new level.</p><p style="text-align: center;"> -----</p><p><span style="-webkit-text-stroke-width: 0px; background-color: white; color: #374151; display: inline !important; float: none; font-family: Satoshi; font-size: 14px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 500; letter-spacing: normal; orphans: 2; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-decoration-thickness: initial; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px;">Attention: Are you in need of professional translation services that will surpass your expectations? Look no further! Leon Tiberiu Cristian is here to provide you with top-notch translation and interpretation services in German, English, and Romanian.
With years of experience in the field, Leon has mastered the art of bridging language barriers and ensuring seamless communication between individuals and businesses. Whether you require translation services for personal documents, business reports, or any other materials, Leon is your go-to professional.
But what sets Leon apart from other translators? It's his commitment to staying at the forefront of translation practice and technology. He utilizes the latest translation applications and computer-aided tools to enhance the accuracy and efficiency of the translation process.
Leon's expertise extends beyond just language translation. He also employs quality assurance tools and terminology management tools to ensure that the final product is of the highest quality and aligns perfectly with your requirements.
Now, you might be wondering, what exactly are translation applications and CAT tools? These powerful tools enable Leon to streamline the translation process, maintain consistency across projects, and deliver translations in a timely manner. By harnessing the power of technology, Leon can handle even the most complex translation projects with ease.
But it doesn't stop there. Leon goes above and beyond to provide exceptional customer service. He takes the time to understand your specific needs and preferences, ensuring that the final translation reflects your unique voice and style.
Don't let language barriers hinder your global communication. Trust Leon Tiberiu Cristian to provide you with accurate, reliable, and efficient translation services. Contact him today to experience the difference firsthand.
Remember, when it comes to translation services, Leon is the name you can trust. Act now and take the first step towards breaking down language barriers.</span> <br /></p>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-14100980386948230052023-09-25T18:53:00.002+03:002023-09-25T19:08:11.952+03:00Python Async Execution Order<pre class="showoutput" id="log"><span style="font-family: times; font-size: small;">import asyncio<br />async def print_(delay, x):<br /> print(f'start: {x}')<br /> await asyncio.sleep(delay)<br /> print(f'end: {x}')<br /><br />async def main():<br /> slow_task = asyncio.create_task(print_(2, 'slow task'))<br /> fast_task = asyncio.create_task(print_(1, 'fast task'))<br /><br /> print(0)<br /> await slow_task<br /> print(1)<br /> await fast_task<br /> print(2)<br /><br />asyncio.run(main())</span></pre><pre class="showoutput" id="log">Output:</pre><pre class="showoutput" id="log">0
start: slow task
start: fast task
end: fast task
end: slow task
1
2</pre><pre class="showoutput" id="log">------ </pre><p>import asyncio<br />async def print_(delay, x):<br /> print(f'start: {x}')<br /> await asyncio.sleep(delay)<br /> print(f'end: {x}')<br /><br />async def main():<br /> slow_task = asyncio.create_task(print_(2, 'slow task'))<br /> fast_task = asyncio.create_task(print_(1, 'fast task'))<br /><br /> print(0)<br /> await fast_task<br /> print(1)<br /> await slow_task<br /> print(2)<br /> <br />asyncio.run(main())</p><p>Output:</p><pre class="showoutput" id="log">0
start: slow task
start: fast task
end: fast task
1
end: slow task
2</pre><pre class="showoutput" id="log"> ----------</pre><pre class="showoutput" id="log"><span style="font-family: times;">import asyncio<br />async def print_(delay, x):<br /> print(f'start: {x}')<br /> await asyncio.sleep(delay)<br /> print(f'end: {x}')<br /><br />async def main():<br /> fast_task = asyncio.create_task(print_(1, 'fast task'))<br /> slow_task = asyncio.create_task(print_(2, 'slow task'))<br /><br /> print(0)<br /> await slow_task<br /> print(1)<br /> await fast_task<br /> print(2)<br /><br />asyncio.run(main())</span></pre><pre class="showoutput" id="log">Output:</pre><pre class="showoutput" id="log">0
start: fast task
start: slow task
end: fast task
end: slow task
1
2 </pre><pre class="showoutput" id="log"><span style="font-family: times;">import asyncio<br />async def print_(delay, x):<br /> print(f'start: {x}')<br /> await asyncio.sleep(delay)<br /> print(f'end: {x}')<br /><br />async def main():<br /> fast_task = asyncio.create_task(print_(1, 'fast task'))<br /> slow_task = asyncio.create_task(print_(2, 'slow task'))<br /><br /> print(0)<br /> await fast_task<br /> print(1)<br /> await slow_task<br /> print(2)<br /></span><br />asyncio.run(main())</pre><pre class="showoutput" id="log">Output:</pre><pre class="showoutput" id="log">0
start: fast task
start: slow task
end: fast task
1
end: slow task
2</pre><p> ******</p><pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">from</span> asyncio <span class="hljs-keyword">import</span> create_task, sleep, run
<span class="hljs-keyword">async</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">print_</span>(<span class="hljs-params">delay, x</span>):
<span class="hljs-built_in">print</span>(<span class="hljs-string">f'start: <span class="hljs-subst">{x}</span>'</span>)
<span class="hljs-keyword">await</span> sleep(delay)
<span class="hljs-built_in">print</span>(<span class="hljs-string">f'end: <span class="hljs-subst">{x}</span>'</span>)
<span class="hljs-keyword">async</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">main</span>():
slow_task = create_task(print_(<span class="hljs-number">2</span>, <span class="hljs-string">'slow task'</span>))
fast_task = create_task(print_(<span class="hljs-number">1</span>, <span class="hljs-string">'fast task'</span>))
<span class="hljs-comment"># The order of execution here is strange:</span>
<span class="hljs-built_in">print</span>(<span class="hljs-number">0</span>)
<span class="hljs-keyword">await</span> slow_task
<span class="hljs-built_in">print</span>(<span class="hljs-number">1</span>)
<span class="hljs-keyword">await</span> fast_task
run(main())</code></pre><ul><li>You create asynchronous processes for a fast task and a slow task at
the same time; even the "fast" one will take a significant amount of
time.</li><li>Immediately after creating them, you print <code>0</code>, so this becomes your first output.</li><li>You call <code>await slow_task</code>, passing control to the event loop until <code>slow_task</code> finishes.
<ul><li>Because you requested <code>slow_task</code>, it's prioritized, so it starts first, so <code>start: slow_task</code> is printed.</li><li>Because <code>slow_task</code> contains an <code>await sleep(2)</code>, it passes control back to the event loop, which finds <code>fast_task</code> as ready to operate and starts it, so <code>start: fast_task</code> is printed.</li><li>Because <code>fast_task</code>'s <code>await sleep(1)</code> finishes first, <code>fast_task</code> completes, and <code>end: fast_task</code> is printed. Because we're <code>await</code>ing <code>slow_task</code>, not <code>fast_task</code>, we remain in the event loop.</li><li>Finally, the slow task finishes, so it prints <code>end: slow task</code>. Because this is what we were <code>await</code>ing for, control flow is returned to the synchronous process.</li></ul>
</li><li>After the slow task has finished, you print <code>1</code>, so this becomes your last output.</li><li>Finally, you wait for the fast task to finish; it already did finish
earlier, while you were waiting for the fast task, so this returns
immediately.</li></ul><pre class="lang-py s-code-block"><code class="hljs language-python"> </code></pre><p> </p>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-63712199346419360002023-09-22T16:30:00.000+03:002023-09-22T16:30:15.517+03:00JS POST Function MMT<p> Nc()((function(e, t, n, a) {<br /> var r = Rn().valueOf(),<br /> i = {<br /> multiline: !0,<br /> source: t,<br /> target: n,<br /> q: e,<br /> hints: a,<br /> ts: r,<br /> verify: ra()("webkey_E3sTuMjpP8Jez49GcYpDVH7r#" + r + "#" + e).toString()<br /> };<br /> return Ra().post("/translate", i, {<br /> headers: {<br /> "X-HTTP-Method-Override": "GET"<br /> }<br /> }).then((function(e) {<br /> var t = e.data.data;<br /> return {<br /> translation: t.translation,<br /> detectedLanguage: t.detectedLanguage<br /> }<br /> }))<br /> }), 800)</p><p> </p><p>ts parameter is the time stamp</p><p>timeStamp = Date.now()</p><h2 id="timestamp-in-milliseconds">Timestamp in milliseconds</h2><figure><pre tabindex="0"><code><span>// 👇 Current timestamp in milliseconds</span>
<span>function</span> <span>getCurrentTimestamp</span><span>(</span><span>)</span> <span>{</span>
<span>return</span> Date<span>.</span><span>now</span><span>(</span><span>)</span><span>;</span>
<span>}</span></code></pre><figcaption>Get the timestamp of the current time in milliseconds.</figcaption></figure><p>The timestamp is milliseconds since January 1, 1970 in UTC. The <code>Date.now()</code> function in JS returns the timestamp of the current time.</p><h3 id="timestamp-from-a-date-string">Timestamp from a date string</h3><p>If you already have a <code>Date</code> object, you can use the prototype methods <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime?ref=code-frontend"></a><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime?ref=code-frontend">getTime</a>() or <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/valueOf?ref=code-frontend"></a><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/valueOf?ref=code-frontend">valueOf</a>() to convert it to timestamp:</p><figure><pre tabindex="0"><code><span>const</span> exactDate <span>=</span> <span>'09/19/2022 10:58:13'</span><span>;</span>
<span>// 👇 Get the timestamp when you already have the date object</span>
<span>const</span> exactDateTimestamp <span>=</span> <span>new</span> <span>Date</span><span>(</span>exactDate<span>)</span><span>.</span><span>getTime</span><span>(</span><span>)</span><span>;</span>
<span>console</span><span>.</span><span>log</span><span>(</span>exactDateTimestamp<span>)</span><span>;</span> <span>// 1663574293000</span></code></pre><figcaption>Convert the date to a timestamp in JS.</figcaption></figure><ol><li>Create a new <code>Date</code> object from a date string by using the constructor.</li><span></span><li>Call the <code>getTime()</code> function on the <code>Date</code> object to get the timestamp in milliseconds.</li><li>Divide the result by <code>1000</code> and round it down to get a Unix timestamp.</li></ol><p>The <code>getTime()</code> and <code>valueOf()</code> functions do the exact same thing and can be used interchangeably.</p><div><p><strong>Note:</strong> depending on the browser settings, such as <code>privacy.reduceTimerPrecision</code> or <code>privacy.resistFingerprinting</code>,
your result may be rounded, and not come in milliseconds. If that can
cause a problem for you, consider implementing your own checks for that.
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime?ref=code-frontend#reduced_time_precision">Read more on MDN</a>.</p></div><p>The Unix timestamp is in seconds rather than milliseconds. Simply divide the timestamp by 1000:</p><code><span>// 👇 To get UNIX timestamp, divide by 1000</span>
<span>function</span> <span>getCurrentUnixTimestamp</span><span>(</span><span>)</span> <span>{</span>
<span>return</span> Math<span>.</span><span>floor</span><span>(</span>Date<span>.</span><span>now</span><span>(</span><span>)</span> <span>/</span> <span>1000</span><span>)</span><span>;</span>
<span>}</span>
<span>const</span> exactDate <span>=</span> <span>'09/19/2022 10:58:13'</span><span>;</span>
<span>// 👇 Get the timestamp when you already have the date object</span>
<span>const</span> exactDateTimestamp <span>=</span> <span>new</span> <span>Date</span><span>(</span>exactDate<span>)</span><span>.</span><span>getTime</span><span>(</span><span>)</span><span>;</span>
<span>console</span><span>.</span><span>log</span><span>(</span>exactDateTimestamp<span>)</span><span>;</span> <span>// 1663574293</span></code><pre tabindex="0"></pre><p></p>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.comtag:blogger.com,1999:blog-494411124526204630.post-77284042534129068792023-09-22T14:15:00.000+03:002023-09-22T14:15:10.456+03:00Translators.py - Python Code<p> # coding=utf-8<br /># author=UlionTse<br /><br />"""<br />Copyright (C) 2017-2023 UlionTse<br /><br />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<br />(at your option) any later version.<br /><br />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.<br /><br />You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/> uliontse@outlook.com<br /><br />translators Copyright (C) 2017-2023 UlionTse<br />This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.<br />This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.<br />"""<br /><br />import os<br />import re<br />import sys<br />import time<br />import json<br />import uuid<br />import hmac<br />import base64<br />import random<br />import hashlib<br />import datetime<br />import warnings<br />import functools<br />import urllib.parse<br />from typing import Optional, Union, Tuple, List<br /><br />import tqdm<br />import execjs<br />import requests<br />import lxml.etree<br />import pathos.multiprocessing<br /><br />SessionType = requests.sessions.Session<br />ResponseType = requests.models.Response<br />LangMapKwargsType = Union[str, bool]<br />ApiKwargsType = Union[str, int, float, bool, dict]<br /><br />__all__ = [<br /> 'translate_text', 'translate_html', 'translators_pool',<br /> 'alibaba', 'apertium', 'argos', 'baidu', 'bing', 'caiyun', 'cloudYi', 'deepl', 'elia', 'google',<br /> 'iciba', 'iflytek', 'iflyrec', 'itranslate', 'judic', 'languageWire', 'lingvanex', 'mglip', 'mirai', 'modernMt',<br /> 'myMemory', 'niutrans', 'papago', 'qqFanyi', 'qqTranSmart', 'reverso', 'sogou', 'sysTran', 'tilde', 'translateCom',<br /> 'translateMe', 'utibet', 'volcEngine', 'yandex', 'yeekit', 'youdao',<br /> '_alibaba', '_apertium', '_argos', '_baidu', '_bing', '_caiyun', '_cloudYi', '_deepl', '_elia', '_google',<br /> '_iciba', '_iflytek', '_iflyrec', '_itranslate', '_judic', '_languageWire', '_lingvanex', '_mglip', '_mirai',<br /> '_modernMt',<br /> '_myMemory', '_niutrans', '_papago', '_qqFanyi', '_qqTranSmart', '_reverso', '_sogou', '_sysTran', '_tilde',<br /> '_translateCom',<br /> '_translateMe', '_utibet', '_volcEngine', '_yandex', '_yeekit', '_youdao',<br />] # 36<br /><br /><br />class TranslatorError(Exception):<br /> pass<br /><br /><br />class Tse:<br /> def __init__(self):<br /> self.author = 'Ulion.Tse'<br /> self.all_begin_time = time.time()<br /> self.default_session_freq = int(1e3)<br /> self.default_session_seconds = 1.5e3<br /> self.transform_en_translator_pool = (<br /> 'itranslate', 'lingvanex', 'myMemory', 'apertium', 'cloudYi', 'translateMe')<br /> self.auto_pool = ('auto', 'detect', 'auto-detect', 'all')<br /> self.zh_pool = ('zh', 'zh-CN', 'zh-cn', 'zh-CHS', 'zh-Hans', 'zh-Hans_CN', 'cn', 'chi', 'Chinese')<br /><br /> @staticmethod<br /> def time_stat(func):<br /> @functools.wraps(func)<br /> def _wrapper(*args, **kwargs):<br /> if_show_time_stat = kwargs.get('if_show_time_stat', False)<br /> show_time_stat_precision = kwargs.get('show_time_stat_precision', 2)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /><br /> if if_show_time_stat and sleep_seconds >= 0:<br /> t1 = time.time()<br /> result = func(*args, **kwargs)<br /> t2 = time.time()<br /> cost_time = round((t2 - t1 - sleep_seconds), show_time_stat_precision)<br /> sys.stderr.write(f'TimeSpent(function: {func.__name__[:-4]}): {cost_time}s\n')<br /> return result<br /> return func(*args, **kwargs)<br /><br /> return _wrapper<br /><br /> @staticmethod<br /> def get_timestamp() -> int:<br /> return int(time.time() * 1e3)<br /><br /> @staticmethod<br /> def get_headers(host_url: str,<br /> if_api: bool = False,<br /> if_referer_for_host: bool = True,<br /> if_ajax_for_api: bool = True,<br /> if_json_for_api: bool = False,<br /> if_multipart_for_api: bool = False,<br /> if_http_override_for_api: bool = False<br /> ) -> dict:<br /><br /> user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"<br /> url_path = urllib.parse.urlparse(host_url.strip('/')).path<br /> host_headers = {<br /> 'Referer' if if_referer_for_host else 'Host': host_url,<br /> "User-Agent": user_agent,<br /> }<br /> api_headers = {<br /> 'Origin': host_url.split(url_path)[0] if url_path else host_url,<br /> 'Referer': host_url,<br /> 'X-Requested-With': 'XMLHttpRequest',<br /> 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',<br /> "User-Agent": user_agent,<br /> }<br /> if if_api and not if_ajax_for_api:<br /> api_headers.pop('X-Requested-With')<br /> api_headers.update({'Content-Type': 'text/plain'})<br /> if if_api and if_json_for_api:<br /> api_headers.update({'Content-Type': 'application/json'})<br /> if if_api and if_multipart_for_api:<br /> api_headers.pop('Content-Type')<br /> if if_api and if_http_override_for_api:<br /> api_headers.update({'X-HTTP-Method-Override': 'GET'})<br /> return host_headers if not if_api else api_headers<br /><br /> def check_en_lang(self, from_lang: str, to_lang: str, default_translator: Optional[str] = None,<br /> default_lang: str = 'en-US') -> Tuple[str, str]:<br /> if default_translator and default_translator in self.transform_en_translator_pool:<br /> from_lang = default_lang if from_lang == 'en' else from_lang<br /> to_lang = default_lang if to_lang == 'en' else to_lang<br /> from_lang = default_lang.replace('-', '_') if default_translator == 'lingvanex' and from_lang[<br /> :3] == 'en-' else from_lang<br /> to_lang = default_lang.replace('-', '_') if default_translator == 'lingvanex' and to_lang[<br /> :3] == 'en-' else to_lang<br /> return from_lang, to_lang<br /><br /> def check_language(self,<br /> from_language: str,<br /> to_language: str,<br /> language_map: dict,<br /> output_auto: str = 'auto',<br /> output_zh: str = 'zh',<br /> output_en_translator: Optional[str] = None,<br /> output_en: str = 'en-US',<br /> if_check_lang_reverse: bool = True,<br /> ) -> Tuple[str, str]:<br /><br /> if output_en_translator:<br /> from_language, to_language = self.check_en_lang(from_language, to_language, output_en_translator, output_en)<br /><br /> from_language = output_auto if from_language in self.auto_pool else from_language<br /> from_language = output_zh if from_language in self.zh_pool else from_language<br /> to_language = output_zh if to_language in self.zh_pool else to_language<br /><br /> if from_language != output_auto and from_language not in language_map:<br /> raise TranslatorError(<br /> 'Unsupported from_language[{}] in {}.'.format(from_language, sorted(language_map.keys())))<br /> elif to_language not in language_map and if_check_lang_reverse:<br /> raise TranslatorError('Unsupported to_language[{}] in {}.'.format(to_language, sorted(language_map.keys())))<br /> elif from_language != output_auto and to_language not in language_map[from_language]:<br /> raise TranslatorError('Unsupported translation: from [{0}] to [{1}]!'.format(from_language, to_language))<br /> elif from_language == to_language:<br /> raise TranslatorError(f'from_language[{from_language}] and to_language[{to_language}] should not be same.')<br /> return from_language, to_language<br /><br /> @staticmethod<br /> def warning_auto_lang(translator: str, default_from_language: str, if_print_warning: bool = True) -> str:<br /> if if_print_warning:<br /> warn_tips = f'Unsupported [from_language=auto({default_from_language} instead)] with [{translator}]!'<br /> warnings.warn(f'{warn_tips} Please specify it.')<br /> return default_from_language<br /><br /> @staticmethod<br /> def debug_lang_kwargs(from_language: str, to_language: str, default_from_language: str,<br /> if_print_warning: bool = True) -> dict:<br /> kwargs = {<br /> 'from_language': from_language,<br /> 'to_language': to_language,<br /> 'default_from_language': default_from_language,<br /> 'if_print_warning': if_print_warning,<br /> }<br /> return kwargs<br /><br /> @staticmethod<br /> def debug_language_map(func):<br /> def make_temp_language_map(from_language: str, to_language: str, default_from_language: str) -> dict:<br /> if from_language == to_language or to_language == 'auto':<br /> raise TranslatorError<br /><br /> temp_language_map = {from_language: to_language}<br /> if from_language != 'auto':<br /> temp_language_map.update({to_language: from_language})<br /> elif default_from_language != to_language:<br /> temp_language_map.update({default_from_language: to_language, to_language: default_from_language})<br /><br /> return temp_language_map<br /><br /> @functools.wraps(func)<br /> def _wrapper(*args, **kwargs):<br /> try:<br /> return func(*args, **kwargs)<br /> except TranslatorError as e:<br /> if kwargs.get('if_print_warning', True):<br /> warnings.warn(f'GetLanguageMapError: {str(e)}.\nThe function make_temp_language_map() works.')<br /> return make_temp_language_map(kwargs.get('from_language'), kwargs.get('to_language'),<br /> kwargs.get('default_from_language'))<br /><br /> return _wrapper<br /><br /> @staticmethod<br /> def check_input_limit(query_text: str, input_limit: int) -> None:<br /> if len(query_text) > input_limit:<br /> raise TranslatorError<br /><br /> @staticmethod<br /> def check_query(func):<br /> def check_query_text(query_text: str,<br /> if_ignore_empty_query: bool,<br /> if_ignore_limit_of_length: bool,<br /> limit_of_length: int<br /> ) -> str:<br /><br /> if not isinstance(query_text, str):<br /> raise TranslatorError<br /><br /> query_text = query_text.strip()<br /> qt_length = len(query_text)<br /> if qt_length == 0 and not if_ignore_empty_query:<br /> raise TranslatorError("The `query_text` can't be empty!")<br /> if qt_length >= limit_of_length and not if_ignore_limit_of_length:<br /> raise TranslatorError('The length of `query_text` exceeds the limit.')<br /> else:<br /> if qt_length >= limit_of_length:<br /> warnings.warn(f'The length of `query_text` is {qt_length}, above {limit_of_length}.')<br /> return query_text[:limit_of_length - 1]<br /> return query_text<br /><br /> @functools.wraps(func)<br /> def _wrapper(*args, **kwargs):<br /> if_ignore_empty_query = kwargs.get('if_ignore_empty_query', False)<br /> if_ignore_limit_of_length = kwargs.get('if_ignore_limit_of_length', False)<br /> limit_of_length = kwargs.get('limit_of_length', 20000)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /><br /> query_text = list(args)[1] if len(args) >= 2 else kwargs.get('query_text')<br /> query_text = check_query_text(query_text, if_ignore_empty_query, if_ignore_limit_of_length, limit_of_length)<br /> if not query_text and if_ignore_empty_query:<br /> return {'data': query_text} if is_detail_result else query_text<br /><br /> if len(args) >= 2:<br /> new_args = list(args)<br /> new_args[1] = query_text<br /> return func(*tuple(new_args), **kwargs)<br /> return func(*args, **{**kwargs, **{'query_text': query_text}})<br /><br /> return _wrapper<br /><br /> @staticmethod<br /> def uncertified(func):<br /> @functools.wraps(func)<br /> def _wrapper(*args, **kwargs):<br /> try:<br /> return func(*args, **kwargs)<br /> except:<br /> raise_tips1 = f'The function {func.__name__[:-4]}() has been not certified yet.'<br /> raise_tips2_url = 'https://github.com/UlionTse/translators#supported-translation-services'<br /> raise_tips2 = f'Please read for details: Status of Translator on this webpage({raise_tips2_url}).'<br /> raise TranslatorError(f'{raise_tips1} {raise_tips2}')<br /><br /> return _wrapper<br /><br /> # @staticmethod<br /> # def certified(func):<br /> # @functools.wraps(func)<br /> # def _wrapper(*args, **kwargs):<br /> # try:<br /> # return func(*args, **kwargs)<br /> # except Exception as e:<br /> # raise TranslatorError(e)<br /> # return _wrapper<br /><br /><br />class GoogleV1(Tse):<br /> def __init__(self, server_region='EN'):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = None<br /> self.cn_host_url = 'https://translate.google.cn'<br /> self.en_host_url = 'https://translate.google.com'<br /> self.api_url = None<br /> self.server_region = server_region<br /> self.host_headers = None<br /> self.language_map = None<br /> self.session = None<br /> self.query_count = 0<br /> self.output_zh = 'zh-CN'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> @staticmethod<br /> def _xr(a: int, b: str) -> int:<br /> size_b = len(b)<br /> c = 0<br /> while c < size_b - 2:<br /> d = b[c + 2]<br /> d = ord(d[0]) - 87 if 'a' <= d else int(d)<br /> d = (a % 2 ** 32) >> d if '+' == b[c + 1] else a << d<br /> a = a + d & (2 ** 32 - 1) if '+' == b[c] else a ^ d<br /> c += 3<br /> return a<br /><br /> @staticmethod<br /> def _ints(text: str) -> List[int]:<br /> ints = []<br /> for v in text:<br /> int_v = ord(v)<br /> if int_v < 2 ** 16:<br /> ints.append(int_v)<br /> else:<br /> # unicode, emoji<br /> ints.append(int((int_v - 2 ** 16) / 2 ** 10 + 55296))<br /> ints.append(int((int_v - 2 ** 16) % 2 ** 10 + 56320))<br /> return ints<br /><br /> def acquire(self, text: str, tkk: str) -> str:<br /> ints = self._ints(text)<br /> size = len(ints)<br /> e = []<br /> g = 0<br /><br /> while g < size:<br /> l = ints[g]<br /> if l < 2 ** 7: # 128(ascii)<br /> e.append(l)<br /> else:<br /> if l < 2 ** 11: # 2048<br /> e.append(l >> 6 | 192)<br /> else:<br /> if (l & 64512) == 55296 and g + 1 < size and ints[g + 1] & 64512 == 56320:<br /> g += 1<br /> l = 65536 + ((l & 1023) << 10) + (ints[g] & 1023)<br /> e.append(l >> 18 | 240)<br /> e.append(l >> 12 & 63 | 128)<br /> else:<br /> e.append(l >> 12 | 224)<br /> e.append(l >> 6 & 63 | 128)<br /> e.append(l & 63 | 128)<br /> g += 1<br /><br /> b = tkk if tkk != '0' else ''<br /> d = b.split('.')<br /> b = int(d[0]) if len(d) > 1 else 0<br /><br /> a = b<br /> for value in e:<br /> a += value<br /> a = self._xr(a, '+-a^+6')<br /> a = self._xr(a, '+-3^+b+-f')<br /> a ^= int(d[1]) if len(d) > 1 else 0<br /> if a < 0:<br /> a = (a & (2 ** 31 - 1)) + 2 ** 31<br /> a %= int(1E6)<br /> return '{}.{}'.format(a, a ^ b)<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, host_html: str, **kwargs: LangMapKwargsType) -> dict:<br /> et = lxml.etree.HTML(host_html)<br /> lang_list = sorted(list(set(et.xpath('//*/@data-language-code'))))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> def get_tkk(self, host_html: str) -> str:<br /> return re.compile("tkk:'(.*?)'").findall(host_html)[0]<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def google_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://translate.google.com, https://translate.google.cn.<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param if_use_cn_host: bool, default None.<br /> :param reset_host_url: str, default None.<br /> :param if_check_reset_host_url: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> reset_host_url = kwargs.get('reset_host_url', None)<br /> if reset_host_url and reset_host_url != self.host_url:<br /> if kwargs.get('if_check_reset_host_url', True) and not reset_host_url[:25] == 'https://translate.google.':<br /> raise TranslatorError<br /> self.host_url = reset_host_url.strip('/')<br /> else:<br /> use_cn_condition = kwargs.get('if_use_cn_host', None) or self.server_region == 'CN'<br /> self.host_url = self.cn_host_url if use_cn_condition else self.en_host_url<br /><br /> if self.host_url[-2:] == 'cn':<br /> raise TranslatorError('Google service was offline in inland of China on Oct 2022.')<br /><br /> self.host_headers = self.host_headers or self.get_headers(self.host_url, if_api=False)<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time and self.api_url):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /><br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(host_html, self.session, timeout, proxies, **debug_lang_kwargs)<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> tkk = self.get_tkk(host_html)<br /> tk = self.acquire(query_text, tkk)<br /><br /> api_url_part_1 = '/translate_a/single?client={0}&sl={1}&tl={2}&hl=zh-CN&dt=at&dt=bd&dt=ex'.format('webapp',<br /> from_language,<br /> to_language)<br /> api_url_part_2 = '&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&ie=UTF-8&oe=UTF-8&source=bh&ssel=0&tsel=0&kc=1'<br /> api_url_part_3 = '&tk={0}&q={1}'.format(tk, urllib.parse.quote(query_text))<br /> self.api_url = ''.join([self.host_url, api_url_part_1, api_url_part_2, api_url_part_3]) # [t,webapp]<br /><br /> r = self.session.get(self.api_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else ''.join([item[0] for item in data[0] if isinstance(item[0], str)])<br /><br /><br />class GoogleV2(Tse):<br /> def __init__(self, server_region='EN'):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = None<br /> self.cn_host_url = 'https://translate.google.cn'<br /> self.en_host_url = 'https://translate.google.com'<br /> self.api_url = None<br /> self.api_url_path = '/_/TranslateWebserverUi/data/batchexecute'<br /> self.server_region = server_region<br /> self.host_headers = None<br /> self.api_headers = None<br /> self.language_map = None<br /> self.session = None<br /> self.rpcid = 'MkEWBc'<br /> self.query_count = 0<br /> self.output_zh = 'zh-CN'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, host_html: str, **kwargs: LangMapKwargsType) -> dict:<br /> et = lxml.etree.HTML(host_html)<br /> lang_list = sorted(list(set(et.xpath('//*/@data-language-code'))))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> def get_rpc(self, query_text: str, from_language: str, to_language: str) -> dict:<br /> param = json.dumps([[query_text, from_language, to_language, True], [1]])<br /> rpc = json.dumps([[[self.rpcid, param, None, "generic"]]])<br /> return {'f.req': rpc}<br /><br /> def get_info(self, host_html: str) -> dict:<br /> data_str = re.compile(r'window.WIZ_global_data = (.*?);</script>').findall(host_html)[0]<br /> data = execjs.eval(data_str)<br /> return {'bl': data['cfb2h'], 'f.sid': data['FdrFJe']}<br /><br /> def get_consent_cookie(self, consent_html: str) -> str: # by mercuree. merged but not verify.<br /> et = lxml.etree.HTML(consent_html)<br /> input_element = et.xpath('.//input[@type="hidden"][@name="v"]')<br /> cookie_value = input_element[0].attrib.get('value') if input_element else 'cb'<br /> return f'CONSENT=YES+{cookie_value}' # cookie CONSENT=YES+cb works for now<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def google_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://translate.google.com, https://translate.google.cn.<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param reset_host_url: str, default None.<br /> :param if_check_reset_host_url: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> reset_host_url = kwargs.get('reset_host_url', None)<br /> if reset_host_url and reset_host_url != self.host_url:<br /> if kwargs.get('if_check_reset_host_url', True) and not reset_host_url[:25] == 'https://translate.google.':<br /> raise TranslatorError<br /> self.host_url = reset_host_url.strip('/')<br /> else:<br /> use_cn_condition = kwargs.get('if_use_cn_host', None) or self.server_region == 'CN'<br /> self.host_url = self.cn_host_url if use_cn_condition else self.en_host_url<br /><br /> if self.host_url[-2:] == 'cn':<br /> raise TranslatorError('Google service was offline in inland of China on Oct 2022.')<br /><br /> self.api_url = f'{self.host_url}{self.api_url_path}'<br /> self.host_headers = self.host_headers or self.get_headers(self.host_url, if_api=False) # reuse cookie header<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_referer_for_host=True, if_ajax_for_api=True)<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> r = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> if 'consent.google.com' == urllib.parse.urlparse(r.url).hostname:<br /> self.host_headers.update({'cookie': self.get_consent_cookie(r.text)})<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> else:<br /> host_html = r.text<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(host_html, **debug_lang_kwargs)<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> rpc_data = self.get_rpc(query_text, from_language, to_language)<br /> rpc_data = urllib.parse.urlencode(rpc_data)<br /> r = self.session.post(self.api_url, headers=self.api_headers, data=rpc_data, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> json_data = json.loads(r.text[6:])<br /> data = json.loads(json_data[0][2])<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return {'data': data} if is_detail_result else ' '.join(<br /> [x[0] for x in (data[1][0][0][5] or data[1][0]) if x[0]])<br /><br /><br />class BaiduV1(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://fanyi.baidu.com'<br /> self.api_url = 'https://fanyi.baidu.com/transapi'<br /> self.get_lang_url = None<br /> self.get_lang_url_pattern = 'https://fanyi-cdn.cdn.bcebos.com/webStatic/translation/js/index.(.*?).js'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True)<br /> self.language_map = None<br /> self.session = None<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> # @Tse.debug_language_map<br /> # def get_language_map(self, host_html: str, **kwargs: LangMapKwargsType) -> dict:<br /> # lang_str = re.compile('langMap: {(.*?)}').search(host_html.replace('\n', '').replace(' ', '')).group()[8:]<br /> # return execjs.eval(lang_str)<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_url: str, ss: SessionType, headers: dict, timeout: Optional[float],<br /> proxies: Optional[dict], **kwargs: LangMapKwargsType) -> dict:<br /> js_html = ss.get(lang_url, headers=headers, timeout=timeout, proxies=proxies).text<br /> lang_str = re.compile('exports={auto:(.*?)}}}},').search(js_html).group()[8:-3]<br /> lang_list = re.compile('(\\w+):{zhName:').findall(lang_str)<br /> lang_list = sorted(list(set(lang_list)))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def baidu_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://fanyi.baidu.com<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies) # must twice, send cookies.<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /><br /> if not self.get_lang_url:<br /> self.get_lang_url = re.compile(self.get_lang_url_pattern).search(host_html).group()<br /><br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.get_lang_url, self.session, self.host_headers, timeout,<br /> proxies, **debug_lang_kwargs)<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> payload = {<br /> 'from': from_language,<br /> 'to': to_language,<br /> 'query': query_text,<br /> 'source': 'txt',<br /> }<br /> r = self.session.post(self.api_url, data=payload, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else '\n'.join([item['dst'] for item in data['data']])<br /><br /><br />class BaiduV2(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://fanyi.baidu.com'<br /> self.api_url = 'https://fanyi.baidu.com/v2transapi'<br /> self.langdetect_url = 'https://fanyi.baidu.com/langdetect'<br /> self.get_sign_url = 'https://fanyi-cdn.cdn.bcebos.com/static/translation/pkg/index_bd36cef.js'<br /> self.get_lang_url = None<br /> self.get_lang_url_pattern = 'https://fanyi-cdn.cdn.bcebos.com/webStatic/translation/js/index.(.*?).js'<br /> self.acs_url = 'https://dlswbr.baidu.com/heicha/mm/{i}/acs-{i}.js'.format(i=2060)<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True)<br /> self.language_map = None<br /> self.session = None<br /> self.professional_field = ('common', 'medicine', 'electronics', 'mechanics', 'novel')<br /> self.token = None<br /> self.sign = None<br /> self.acs_token = None<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_url: str, ss: SessionType, headers: dict, timeout: Optional[float],<br /> proxies: Optional[dict], **kwargs: LangMapKwargsType) -> dict:<br /> js_html = ss.get(lang_url, headers=headers, timeout=timeout, proxies=proxies).text<br /> lang_str = re.compile('exports={auto:(.*?)}}}},').search(js_html).group()[8:-3]<br /> lang_list = re.compile('(\\w+):{zhName:').findall(lang_str)<br /> lang_list = sorted(list(set(lang_list)))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> def get_sign(self, query_text: str, host_html: str, ss: SessionType, headers: dict, timeout: float,<br /> proxies: dict) -> str:<br /> gtk_list = re.compile("""window.gtk = '(.*?)';|window.gtk = "(.*?)";""").findall(host_html)[0]<br /> gtk = gtk_list[0] or gtk_list[1]<br /><br /> sign_html = ss.get(self.get_sign_url, headers=headers, timeout=timeout, proxies=proxies).text<br /> begin_label = 'define("translation:widget/translate/input/pGrab",function(r,o,t){'<br /> end_label = 'var i=null;t.exports=e});'<br /> sign_js = sign_html[sign_html.find(begin_label) + len(begin_label):sign_html.find(end_label)]<br /> sign_js = sign_js.replace('function e(r)', 'function e(r,i)')<br /> return execjs.compile(sign_js).call('e', query_text, gtk)<br /><br /> def get_tk(self, host_html: str) -> str:<br /> tk_list = re.compile("""token: '(.*?)',|token: "(.*?)",""").findall(host_html)[0]<br /> return tk_list[0] or tk_list[1]<br /><br /> # def get_acs_token(self):<br /> # pass<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def baidu_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://fanyi.baidu.com<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param professional_field: str, default 'common'. Choose from ('common', 'medicine', 'electronics', 'mechanics', 'novel')<br /> :return: str or dict<br /> """<br /><br /> use_domain = kwargs.get('professional_field', 'common')<br /> if use_domain not in self.professional_field: # only support zh-en, en-zh.<br /> raise TranslatorError<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (<br /> self.session and self.language_map and not_update_cond_freq and not_update_cond_time and self.token and self.sign):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies) # must twice, send cookies.<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> self.token = self.get_tk(host_html)<br /> self.sign = self.get_sign(query_text, host_html, self.session, self.host_headers, timeout, proxies)<br /><br /> if not self.get_lang_url:<br /> self.get_lang_url = re.compile(self.get_lang_url_pattern).search(host_html).group()<br /><br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.get_lang_url, self.session, self.host_headers, timeout,<br /> proxies, **debug_lang_kwargs)<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /> if from_language == 'auto':<br /> res = self.session.post(self.langdetect_url, headers=self.api_headers, data={"query": query_text},<br /> timeout=timeout, proxies=proxies)<br /> from_language = res.json()['lan']<br /><br /> params = {"from": from_language, "to": to_language}<br /> payload = {<br /> "from": from_language,<br /> "to": to_language,<br /> "query": query_text, # from urllib.parse import quote_plus<br /> "transtype": "realtime", # ["translang","realtime"]<br /> "simple_means_flag": "3",<br /> "sign": self.sign,<br /> "token": self.token,<br /> "domain": use_domain,<br /> }<br /> payload = urllib.parse.urlencode(payload).encode('utf-8')<br /> # self.api_headers.update({'Acs-Token': self.acs_token})<br /> r = self.session.post(self.api_url, params=params, data=payload, headers=self.api_headers, timeout=timeout,<br /> proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else '\n'.join([x['dst'] for x in data['trans_result']['data']])<br /><br /><br />class YoudaoV1(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://fanyi.youdao.com'<br /> self.api_url = 'https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'<br /> self.language_url = 'https://api-overmind.youdao.com/openapi/get/luna/dict/luna-front/prod/langType'<br /> self.get_sign_old_url = 'https://shared.ydstatic.com/fanyi/newweb/v1.0.29/scripts/newweb/fanyi.min.js'<br /> self.get_sign_url = None<br /> self.get_sign_pattern = 'https://shared.ydstatic.com/fanyi/newweb/(.*?)/scripts/newweb/fanyi.min.js'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True)<br /> self.language_map = None<br /> self.session = None<br /> self.sign_key = None<br /> self.query_count = 0<br /> self.output_zh = 'zh-CHS'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> # @Tse.debug_language_map<br /> # def get_language_map(self, host_html: str, **kwargs: LangMapKwargsType) -> dict:<br /> # et = lxml.etree.HTML(host_html)<br /> # lang_list = et.xpath('//*[@id="languageSelect"]/li/@data-value')<br /> # lang_list = [(x.split('2')[0], [x.split('2')[1]]) for x in lang_list if '2' in x]<br /> # lang_map = dict(map(lambda x: x, lang_list))<br /> # lang_map.pop('zh-CHS')<br /> # lang_map.update({'zh-CHS': list(lang_map.keys())})<br /> # return lang_map<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_url: str, ss: SessionType, headers: dict, timeout: Optional[float],<br /> proxies: Optional[dict], **kwargs: LangMapKwargsType) -> dict:<br /> data = ss.get(lang_url, headers=headers, timeout=timeout, proxies=proxies).json()<br /> lang_list = sorted([it['code'] for it in data['data']['value']['textTranslate']['specify']])<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> def get_sign_key(self, host_html: str, ss: SessionType, timeout: float, proxies: dict) -> str:<br /> try:<br /> if not self.get_sign_url:<br /> self.get_sign_url = re.compile(self.get_sign_pattern).search(host_html).group()<br /> r = ss.get(self.get_sign_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> except:<br /> r = ss.get(self.get_sign_old_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> sign = re.compile('md5\\("fanyideskweb" \\+ e \\+ i \\+ "(.*?)"\\)').findall(r.text)<br /> return sign[0] if sign and sign != [''] else "Ygy_4c=r#e#4EX^NUGUc5" # v1.1.10<br /><br /> def get_form(self, query_text: str, from_language: str, to_language: str, sign_key: str) -> dict:<br /> ts = str(self.get_timestamp())<br /> salt = str(ts) + str(random.randrange(0, 10))<br /> sign_text = ''.join(['fanyideskweb', query_text, salt, sign_key])<br /> sign = hashlib.md5(sign_text.encode()).hexdigest()<br /> bv = hashlib.md5(self.api_headers['User-Agent'][8:].encode()).hexdigest()<br /> form = {<br /> 'i': query_text,<br /> 'from': from_language,<br /> 'to': to_language,<br /> 'lts': ts, # r = "" + (new Date).getTime()<br /> 'salt': salt, # i = r + parseInt(10 * Math.random(), 10)<br /> 'sign': sign, # n.md5("fanyideskweb" + e + i + "n%A-rKaT5fb[Gy?;N5@Tj"),e=text<br /> 'bv': bv, # n.md5(navigator.appVersion)<br /> 'smartresult': 'dict',<br /> 'client': 'fanyideskweb',<br /> 'doctype': 'json',<br /> 'version': '2.1',<br /> 'keyfrom': 'fanyi.web',<br /> 'action': 'FY_BY_REALTlME',<br /> # not time.["FY_BY_REALTlME", "FY_BY_DEFAULT", "FY_BY_CLICKBUTTION", "lan-select"]<br /> # 'typoResult': 'false'<br /> }<br /> return form<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def youdao_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://fanyi.youdao.com<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time and self.sign_key):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> self.sign_key = self.get_sign_key(host_html, self.session, timeout, proxies)<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.language_url, self.session, self.host_headers, timeout,<br /> proxies, **debug_lang_kwargs)<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> form = self.get_form(query_text, from_language, to_language, self.sign_key)<br /> r = self.session.post(self.api_url, data=form, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else '\n'.join(<br /> [' '.join([it['tgt'] for it in item]) for item in data['translateResult']])<br /><br /><br />class YoudaoV2(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://fanyi.youdao.com'<br /> self.api_url = 'https://dict.youdao.com/webtranslate'<br /> self.api_host = 'https://dict.youdao.com'<br /> self.get_js_url = None<br /> self.get_js_pattern = 'js/app.(.*?).js'<br /> self.get_sign_url = None<br /> self.get_sign_pattern = ''<br /> self.login_url = 'https://dict.youdao.com/login/acc/query/accountinfo'<br /> self.language_url = 'https://api-overmind.youdao.com/openapi/get/luna/dict/luna-front/prod/langType'<br /> self.domain_url = 'https://doctrans-service.youdao.com/common/enums/list?key=domain'<br /> self.get_key_url = 'https://dict.youdao.com/webtranslate/key'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True)<br /> self.api_headers.update({'Host': self.api_host})<br /> self.language_map = None<br /> self.session = None<br /> self.professional_field = ('0', '1', '2', '3')<br /> self.professional_field_map = None<br /> self.default_key = None<br /> self.secret_key = None<br /> self.decode_key = None<br /> self.decode_iv = None<br /> self.query_count = 0<br /> self.output_zh = 'zh-CHS'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_url: str, ss: SessionType, headers: dict, timeout: Optional[float],<br /> proxies: Optional[dict], **kwargs: LangMapKwargsType) -> dict:<br /> data = ss.get(lang_url, headers=headers, timeout=timeout, proxies=proxies).json()<br /> lang_list = sorted([it['code'] for it in data['data']['value']['textTranslate']['specify']])<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> def get_default_key(self, js_html: str) -> str:<br /> return re.compile('="webfanyi-key-getter",(\\w+)="(\\w+)";').search(js_html).group(2)<br /><br /> def get_sign(self, key: str, timestmp: int) -> str:<br /> value = f'client=fanyideskweb&mysticTime={timestmp}&product=webfanyi&key={key}'<br /> return hashlib.md5(value.encode()).hexdigest()<br /><br /> def get_payload(self, keyid: str, key: str, timestamp: int, **kwargs: str) -> dict:<br /> if keyid not in ('webfanyi-key-getter', 'webfanyi'):<br /> raise TranslatorError<br /><br /> payload = {<br /> 'keyid': keyid,<br /> 'mysticTime': str(timestamp),<br /> 'sign': self.get_sign(key, timestamp),<br /> 'client': 'fanyideskweb',<br /> 'product': 'webfanyi',<br /> 'appVersion': '1.0.0',<br /> 'vendor': 'web',<br /> 'keyfrom': 'fanyi.web',<br /> 'pointParam': 'client,mysticTime,product',<br /> }<br /> return {**kwargs, **payload} if keyid == 'webfanyi' else payload<br /><br /> def decrypt(self, cipher_text: str, decrypt_dictionary: dict) -> str:<br /> _ciphertext = ''.join(list(map(lambda k: decrypt_dictionary[k], cipher_text)))<br /> return base64.b64decode(_ciphertext).decode()<br /><br /> @Tse.uncertified<br /> @Tse.time_stat<br /> @Tse.check_query<br /> def youdao_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://fanyi.youdao.com<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param professional_field: str, default '0'. Choose from ('0','1','2','3')<br /> :return: str or dict<br /> """<br /><br /> domain = kwargs.get('professional_field', '0')<br /> if domain not in self.professional_field:<br /> raise TranslatorError<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (<br /> self.session and self.language_map and not_update_cond_freq and not_update_cond_time and self.secret_key):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> _ = self.session.get(self.login_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> self.professional_field_map = \<br /> self.session.get(self.domain_url, headers=self.host_headers, timeout=timeout, proxies=proxies).json()[<br /> 'data']<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.language_url, self.session, self.host_headers, timeout,<br /> proxies, **debug_lang_kwargs)<br /><br /> self.get_js_url = ''.join([self.host_url, '/', re.compile(self.get_js_pattern).search(host_html).group()])<br /> js_html = self.session.get(self.get_js_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /><br /> self.decode_key = re.compile('decodeKey:"(.*?)",').search(js_html).group(1)<br /> self.decode_iv = re.compile('decodeIv:"(.*?)",').search(js_html).group(1)<br /> self.default_key = self.get_default_key(js_html)<br /><br /> params = self.get_payload(keyid='webfanyi-key-getter', key=self.default_key, timestamp=self.get_timestamp())<br /> key_r = self.session.get(self.get_key_url, params=params, headers=self.api_headers, timeout=timeout,<br /> proxies=proxies)<br /> self.secret_key = key_r.json()['data']['secretKey']<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> translate_form = {<br /> 'i': query_text,<br /> 'from': from_language,<br /> 'to': to_language if from_language != 'auto' else '',<br /> 'domain': domain,<br /> 'dictResult': 'true',<br /> }<br /> payload = self.get_payload(keyid='webfanyi', key=self.default_key, timestamp=self.get_timestamp(),<br /> **translate_form)<br /> payload = urllib.parse.urlencode(payload)<br /> r = self.session.post(self.api_url, data=payload, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status() # raise TranslatorError('YoudaoV2 has not been completed.') # TODO<br /> data = self.decrypt(r.text, decrypt_dictionary={})<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else str(data) # TODO<br /><br /><br />class YoudaoV3(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://ai.youdao.com/product-fanyi-text.s'<br /> self.api_url = 'https://aidemo.youdao.com/trans'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True)<br /> self.language_map = None<br /> self.session = None<br /> self.query_count = 0<br /> self.output_zh = 'zh-CHS'<br /> self.input_limit = int(1e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, host_html: str, **kwargs: LangMapKwargsType) -> dict:<br /> et = lxml.etree.HTML(host_html)<br /> lang_list = et.xpath('//*[@id="customSelectOption"]/li/a/@val')<br /> lang_list = sorted([it.split('2')[1] for it in lang_list if f'{self.output_zh}2' in it])<br /> return {**{lang: [self.output_zh] for lang in lang_list}, **{self.output_zh: lang_list}}<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def youdao_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://ai.youdao.com/product-fanyi-text.s<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(host_html, **debug_lang_kwargs)<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /> if from_language == 'auto':<br /> from_language = to_language = 'Auto'<br /><br /> payload = {'q': query_text, 'from': from_language, 'to': to_language}<br /> payload = urllib.parse.urlencode(payload)<br /> r = self.session.post(self.api_url, data=payload, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['translation'][0]<br /><br /><br />class QQFanyi(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://fanyi.qq.com'<br /> self.api_url = 'https://fanyi.qq.com/api/translate'<br /> self.get_language_url = 'https://fanyi.qq.com/js/index.js'<br /> self.get_qt_url = 'https://fanyi.qq.com/api/reauth12f'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True)<br /> self.qt_headers = self.get_headers(self.host_url, if_api=True, if_json_for_api=True)<br /> self.language_map = None<br /> self.session = None<br /> self.qtv_qtk = None<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(2e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, ss: SessionType, language_url: str, timeout: Optional[float], proxies: Optional[dict],<br /> **kwargs: LangMapKwargsType) -> dict:<br /> r = ss.get(language_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> lang_map_str = re.compile('C={(.*?)}|languagePair = {(.*?)}', flags=re.S).search(r.text).group() # C=<br /> return execjs.eval(lang_map_str)<br /><br /> def get_qt(self, ss: SessionType, timeout: float, proxies: dict) -> dict:<br /> return ss.post(self.get_qt_url, headers=self.qt_headers, json=self.qtv_qtk, timeout=timeout,<br /> proxies=proxies).json()<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def qqFanyi_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://fanyi.qq.com<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time and self.qtv_qtk):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies).text<br /> self.qtv_qtk = self.get_qt(self.session, timeout, proxies)<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.session, self.get_language_url, timeout, proxies,<br /> **debug_lang_kwargs)<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> payload = {<br /> 'source': from_language,<br /> 'target': to_language,<br /> 'sourceText': query_text,<br /> 'qtv': self.qtv_qtk.get('qtv', ''),<br /> 'qtk': self.qtv_qtk.get('qtk', ''),<br /> 'ticket': '',<br /> 'randstr': '',<br /> 'sessionUuid': f'translate_uuid{self.get_timestamp()}',<br /> }<br /> r = self.session.post(self.api_url, headers=self.api_headers, data=payload, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else ''.join(<br /> item['targetText'] for item in data['translate']['records']) # auto whitespace<br /><br /><br />class QQTranSmart(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://transmart.qq.com'<br /> self.api_url = 'https://transmart.qq.com/api/imt'<br /> self.get_lang_url = None<br /> self.get_lang_url_pattern = '/assets/vendor.(.*?).js' # e4c6831c<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_json_for_api=True)<br /> self.language_map = None<br /> self.session = None<br /> self.uuid = str(uuid.uuid4())<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_url: str, ss: SessionType, timeout: Optional[float], proxies: Optional[dict],<br /> **kwargs: LangMapKwargsType) -> dict:<br /> js_html = ss.get(lang_url, headers=self.host_headers, timeout=timeout, proxies=proxies).text<br /> lang_str_list = re.compile('lngs:\\[(.*?)]').findall(js_html) # 'lngs:\\[(.*?)\\]'<br /> lang_list = [execjs.eval(f'[{x}]') for x in lang_str_list]<br /> lang_list = sorted(list(set([lang for langs in lang_list for lang in langs])))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> def get_clientKey(self) -> str:<br /> return f'browser-firefox-110.0.0-Windows 10-{self.uuid}-{self.get_timestamp()}'<br /><br /> def split_sentence(self, data: dict) -> List[str]:<br /> index_pair_list = [[item['start'], item['start'] + item['len']] for item in data['sentence_list']]<br /> index_list = [i for ii in index_pair_list for i in ii]<br /> return [data['text'][index_list[i]: index_list[i + 1]] for i in range(len(index_list) - 1)]<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def qqTranSmart_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://transmart.qq.com<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /><br /> if not self.get_lang_url:<br /> self.get_lang_url = f'{self.host_url}{re.compile(self.get_lang_url_pattern).search(host_html).group()}'<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.get_lang_url, self.session, timeout, proxies,<br /> **debug_lang_kwargs)<br /><br /> if from_language == 'auto':<br /> from_language = self.warning_auto_lang('qqTranSmart', self.default_from_language, if_print_warning)<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> client_key = self.get_clientKey()<br /> self.api_headers.update({'Cookie': f'client_key={client_key}'})<br /><br /> split_payload = {<br /> 'header': {<br /> 'fn': 'text_analysis',<br /> 'client_key': client_key,<br /> },<br /> 'type': 'plain',<br /> 'text': query_text,<br /> 'normalize': {'merge_broken_line': 'false'}<br /> }<br /> split_data = self.session.post(self.api_url, json=split_payload, headers=self.api_headers, timeout=timeout,<br /> proxies=proxies).json()<br /> text_list = self.split_sentence(split_data)<br /><br /> api_payload = {<br /> 'header': {<br /> 'fn': 'auto_translation',<br /> 'client_key': client_key,<br /> },<br /> 'type': 'plain',<br /> 'model_category': 'normal',<br /> 'source': {<br /> 'lang': from_language,<br /> 'text_list': [''] + text_list + [''],<br /> },<br /> 'target': {'lang': to_language}<br /> }<br /> r = self.session.post(self.api_url, json=api_payload, headers=self.api_headers, timeout=timeout,<br /> proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else ''.join(data['auto_translation'])<br /><br /><br />class AlibabaV1(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://translate.alibaba.com'<br /> self.api_url = 'https://translate.alibaba.com/translationopenseviceapp/trans/TranslateTextAddAlignment.do'<br /> self.get_language_url = 'https://translate.alibaba.com/translationopenseviceapp/trans/acquire_supportLanguage.do'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True)<br /> self.language_map = None<br /> self.professional_field = ("general", "message", "offer")<br /> self.dmtrack_pageid = None<br /> self.session = None<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> def get_dmtrack_pageid(self, host_response: ResponseType) -> str:<br /> try:<br /> e = re.compile("dmtrack_pageid='(\\w+)';").findall(host_response.text)[0]<br /> except:<br /> e = ''<br /> if not e:<br /> e = host_response.cookies.get_dict().get("cna", "001")<br /> e = re.compile('[^a-z\\d]').sub(repl='', string=e.lower())[:16]<br /> else:<br /> n, r = e[0:16], e[16:26]<br /> i = hex(int(r, 10))[2:] if re.compile('^[\\-+]?[0-9]+$').match(r) else r<br /> e = n + i<br /><br /> s = self.get_timestamp()<br /> o = ''.join([e, hex(s)[2:]])<br /> for _ in range(1, 10):<br /> a = hex(int(0 * 1e10))[2:] # int->str: 16, '0x'<br /> o += a<br /> return o[:42]<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, ss: SessionType, lang_url: str, use_domain: str, dmtrack_pageid: str,<br /> timeout: Optional[float], proxies: Optional[dict], **kwargs: LangMapKwargsType) -> dict:<br /> params = {'dmtrack_pageid': dmtrack_pageid, 'biz_type': use_domain}<br /> language_dict = ss.get(lang_url, params=params, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).json()<br /> return dict(map(lambda x: x, [(x['sourceLuange'], x['targetLanguages']) for x in language_dict['languageMap']]))<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def alibaba_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://translate.alibaba.com<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param professional_field: str, default 'message', choose from ("general","message","offer")<br /> :return: str or dict<br /> """<br /><br /> use_domain = kwargs.get('professional_field', 'message')<br /> if use_domain not in self.professional_field:<br /> raise TranslatorError<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (<br /> self.session and self.language_map and not_update_cond_freq and not_update_cond_time and self.dmtrack_pageid):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_response = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> self.dmtrack_pageid = self.get_dmtrack_pageid(host_response)<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.session, self.get_language_url, use_domain,<br /> self.dmtrack_pageid, timeout, proxies, **debug_lang_kwargs)<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /> payload = {<br /> "srcLanguage": from_language,<br /> "tgtLanguage": to_language,<br /> "srcText": query_text,<br /> "bizType": use_domain,<br /> "viewType": "",<br /> "source": "",<br /> }<br /> params = {"dmtrack_pageid": self.dmtrack_pageid}<br /> r = self.session.post(self.api_url, headers=self.api_headers, params=params, data=payload, timeout=timeout,<br /> proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['listTargetText'][0]<br /><br /><br />class AlibabaV2(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://translate.alibaba.com'<br /> self.api_url = 'https://translate.alibaba.com/api/translate/text'<br /> self.csrf_url = 'https://translate.alibaba.com/api/translate/csrftoken'<br /> self.get_language_pattern = '//lang.alicdn.com/mcms/translation-open-portal/(.*?)/translation-open-portal_interface.json'<br /> self.get_language_url = None<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_ajax_for_api=False,<br /> if_multipart_for_api=True)<br /> self.language_map = None<br /> self.detail_language_map = None<br /> self.professional_field = ('general',)<br /> self.csrf_token = None<br /> self.session = None<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_html: str, **kwargs: LangMapKwargsType) -> dict:<br /> lang_paragraph = re.compile('"en_US":{(.*?)},"zh_CN":{').search(lang_html).group().replace('",', '",\n')<br /> lang_items = re.compile('interface.(.*?)":"(.*?)"').findall(lang_paragraph)<br /> _fn_filter = lambda k, v: 1 if (len(k) <= 3 or (len(k) == 5 and '-' in k)) and len(v.split(' ')) <= 2 else 0<br /> lang_items = sorted([(k, v) for k, v in lang_items if _fn_filter(k, v)])<br /> d_lang_map = {k: v for k, v in lang_items}<br /> lang_list = list(d_lang_map.keys())<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> def get_d_lang_map(self, lang_html: str) -> dict:<br /> lang_paragraph = re.compile('"en_US":{(.*?)},"zh_CN":{').search(lang_html).group().replace('",', '",\n')<br /> lang_items = re.compile('interface.(.*?)":"(.*?)"').findall(lang_paragraph)<br /> _fn_filter = lambda k, v: 1 if (len(k) <= 3 or (len(k) == 5 and '-' in k)) and len(v.split(' ')) <= 2 else 0<br /> lang_items = sorted([(k, v) for k, v in lang_items if _fn_filter(k, v)])<br /> return {k: v for k, v in lang_items}<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def alibaba_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://translate.alibaba.com<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param professional_field: str, default 'message', choose from ("general",)<br /> :return: str or dict<br /> """<br /><br /> use_domain = kwargs.get('professional_field', 'general')<br /> if use_domain not in self.professional_field:<br /> raise TranslatorError<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (<br /> self.session and self.language_map and not_update_cond_freq and not_update_cond_time and self.csrf_token):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> self.get_language_url = f'https:{re.compile(self.get_language_pattern).search(host_html).group()}'<br /> lang_html = self.session.get(self.get_language_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(lang_html, **debug_lang_kwargs)<br /> self.detail_language_map = self.get_d_lang_map(lang_html)<br /><br /> _ = self.session.get(self.csrf_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> self.csrf_token = self.session.get(self.csrf_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).json()<br /> self.api_headers.update({self.csrf_token['headerName']: self.csrf_token['token']})<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map, self.output_zh)<br /> files_data = {<br /> 'query': (None, query_text),<br /> 'srcLang': (None, from_language),<br /> 'tgtLang': (None, to_language),<br /> '_csrf': (None, self.csrf_token['token']),<br /> 'domain': (None, self.professional_field[0]),<br /> } # Content-Type: multipart/form-data<br /> r = self.session.post(self.api_url, files=files_data, headers=self.api_headers, timeout=timeout,<br /> proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['data']['translateText']<br /><br /><br />class Bing(Tse):<br /> def __init__(self, server_region='EN'):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = None<br /> self.cn_host_url = 'https://cn.bing.com/Translator'<br /> self.en_host_url = 'https://www.bing.com/Translator'<br /> self.server_region = server_region<br /> self.api_url = None<br /> self.host_headers = None<br /> self.api_headers = None<br /> self.language_map = None<br /> self.session = None<br /> self.tk = None<br /> self.ig_iid = None<br /> self.query_count = 0<br /> self.output_auto = 'auto-detect'<br /> self.output_zh = 'zh-Hans'<br /> self.input_limit = int(1e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, host_html: str, **kwargs: LangMapKwargsType) -> dict:<br /> et = lxml.etree.HTML(host_html)<br /> lang_list = et.xpath('//*[@id="tta_srcsl"]/option/@value') or et.xpath('//*[@id="t_srcAllLang"]/option/@value')<br /> lang_list = sorted(list(set(lang_list)))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> def get_ig_iid(self, host_html: str) -> dict:<br /> et = lxml.etree.HTML(host_html)<br /> # iid = et.xpath('//*[@id="tta_outGDCont"]/@data-iid')[0] # browser page is different between request page.<br /> iid = 'translator.5028'<br /> ig = re.compile('IG:"(.*?)"').findall(host_html)[0]<br /> return {'iid': iid, 'ig': ig}<br /><br /> def get_tk(self, host_html: str) -> dict:<br /> result_str = re.compile('var params_AbusePreventionHelper = (.*?);').findall(host_html)[0]<br /> result = execjs.eval(result_str)<br /> return {'key': result[0], 'token': result[1]}<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def bing_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://bing.com/Translator, https://cn.bing.com/Translator.<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param if_use_cn_host: bool, default None.<br /> :return: str or dict<br /> """<br /><br /> use_cn_condition = kwargs.get('if_use_cn_host', None) or self.server_region == 'CN'<br /> self.host_url = self.cn_host_url if use_cn_condition else self.en_host_url<br /> self.api_url = self.host_url.replace('Translator', 'ttranslatev3')<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True)<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (<br /> self.session and self.language_map and not_update_cond_freq and not_update_cond_time and self.tk and self.ig_iid):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> self.tk = self.get_tk(host_html)<br /> self.ig_iid = self.get_ig_iid(host_html)<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(host_html, **debug_lang_kwargs)<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh, output_auto=self.output_auto)<br /><br /> payload = {<br /> 'text': query_text,<br /> 'fromLang': from_language,<br /> 'to': to_language,<br /> 'tryFetchingGenderDebiasedTranslations': 'true'<br /> }<br /> payload = {**payload, **self.tk}<br /> api_url_param = f'?isVertical=1&&IG={self.ig_iid["ig"]}&IID={self.ig_iid["iid"]}'<br /> api_url = ''.join([self.api_url, api_url_param])<br /> r = self.session.post(api_url, headers=self.host_headers, data=payload, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data[0] if is_detail_result else data[0]['translations'][0]['text']<br /><br /><br />class Sogou(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://fanyi.sogou.com/text'<br /> self.api_url = 'https://fanyi.sogou.com/api/transpc/text/result'<br /> self.get_language_old_url = 'https://search.sogoucdn.com/translate/pc/static/js/app.7016e0df.js'<br /> self.get_language_pattern = '//search.sogoucdn.com/translate/pc/static/js/vendors.(.*?).js'<br /> self.get_language_url = None<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True)<br /> self.language_map = None<br /> self.uuid = None<br /> self.session = None<br /> self.query_count = 0<br /> self.output_zh = 'zh-CHS'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, host_html: str, lang_old_url: str, ss: SessionType, timeout: Optional[float],<br /> proxies: Optional[dict], **kwargs: LangMapKwargsType) -> dict:<br /> try:<br /> if not self.get_language_url:<br /> lang_url_path = re.compile(self.get_language_pattern).search(host_html).group()<br /> self.get_language_url = ''.join(['https:', lang_url_path])<br /> lang_html = ss.get(self.get_language_url, headers=self.host_headers, timeout=timeout, proxies=proxies).text<br /> except:<br /> lang_html = ss.get(lang_old_url, headers=self.host_headers, timeout=timeout, proxies=proxies).text<br /><br /> lang_list_str = re.compile('"ALL":\\[(.*?)]').search(lang_html).group().replace('!0', '1').replace('!1', '0')[<br /> 6:]<br /> lang_item_list = json.loads(lang_list_str)<br /> lang_list = [item['lang'] for item in lang_item_list if item['play'] == 1]<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> # def get_uuid(self) -> str:<br /> # _uuid = ''<br /> # for i in range(8):<br /> # _uuid += hex(int(65536 * (1 + 0)))[2:][1:]<br /> # if i in range(1, 5):<br /> # _uuid += '-'<br /> # return _uuid<br /><br /> def get_form(self, query_text: str, from_language: str, to_language: str, uid: str) -> dict:<br /> sign_text = "" + from_language + to_language + query_text + '109984457' # window.__INITIAL_STATE__.common.CONFIG.secretCode<br /> sign = hashlib.md5(sign_text.encode()).hexdigest()<br /> form = {<br /> "from": from_language,<br /> "to": to_language,<br /> "text": query_text,<br /> "uuid": uid,<br /> "s": sign,<br /> "client": "pc", # wap<br /> "fr": "browser_pc", # browser_wap<br /> "needQc": "1",<br /> }<br /> return form<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def sogou_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://fanyi.sogou.com/text<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time and self.uuid):<br /> self.uuid = str(uuid.uuid4())<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(host_html, self.get_language_old_url, self.session, timeout,<br /> proxies, **debug_lang_kwargs)<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> payload = self.get_form(query_text, from_language, to_language, self.uuid)<br /> r = self.session.post(self.api_url, headers=self.api_headers, data=payload, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['data']['translate']['dit']<br /><br /><br />class Caiyun(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://fanyi.caiyunapp.com'<br /> self.api_url = 'https://api.interpreter.caiyunai.com/v1/translator'<br /> self.get_js_pattern = '/assets/index.(.*?).js'<br /> self.get_js_url = None<br /> self.get_jwt_url = 'https://api.interpreter.caiyunai.com/v1/user/jwt/generate'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False, if_referer_for_host=True)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_ajax_for_api=False, if_json_for_api=True)<br /> self.language_map = None<br /> self.session = None<br /> self.professional_field = (None, "medicine", "law", "machinery",)<br /> self.browser_data = {'browser_id': ''.join(random.sample('abcdefghijklmnopqrstuvwxyz0123456789', 32))}<br /> self.normal_key = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' + '0123456789' + '=.+-_/'<br /> self.cipher_key = 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm' + '0123456789' + '=.+-_/'<br /> self.decrypt_dictionary = self.crypt(if_de=True)<br /> self.tk = None<br /> self.jwt = None<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, js_html: str, **kwargs: LangMapKwargsType) -> dict:<br /> return execjs.eval(re.compile('={auto:\\[(.*?)}').search(js_html).group()[1:])<br /><br /> def get_tk(self, js_html: str) -> str:<br /> return re.compile('headers\\["X-Authorization"]="(.*?)",').findall(js_html)[0]<br /><br /> # def get_jwt(self, browser_id: str, api_headers: dict, ss: SessionType, timeout: float, proxies: dict) -> str:<br /> # data = {"browser_id": browser_id}<br /> # return ss.post(self.get_jwt_url, json=data, headers=api_headers, timeout=timeout, proxies=proxies).json()['jwt']<br /><br /> def crypt(self, if_de: bool = True) -> dict:<br /> if if_de:<br /> return {k: v for k, v in zip(self.cipher_key, self.normal_key)}<br /> return {v: k for k, v in zip(self.cipher_key, self.normal_key)}<br /><br /> def encrypt(self, plain_text: str) -> str:<br /> encrypt_dictionary = self.crypt(if_de=False)<br /> _cipher_text = base64.b64encode(plain_text.encode()).decode()<br /> return ''.join(list(map(lambda k: encrypt_dictionary[k], _cipher_text)))<br /><br /> def decrypt(self, cipher_text: str) -> str:<br /> _ciphertext = ''.join(list(map(lambda k: self.decrypt_dictionary[k], cipher_text)))<br /> return base64.b64decode(_ciphertext).decode()<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def caiyun_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://fanyi.caiyunapp.com<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param professional_field: str, default None, choose from (None, "medicine","law","machinery")<br /> :return: str or dict<br /> """<br /><br /> use_domain = kwargs.get('professional_field', None)<br /> if use_domain not in (None, "medicine", "law", "machinery"):<br /> raise TranslatorError<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (<br /> self.session and self.language_map and not_update_cond_freq and not_update_cond_time and self.tk and self.jwt):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> js_url_path = re.compile(self.get_js_pattern).search(host_html).group()<br /> self.get_js_url = ''.join([self.host_url, js_url_path])<br /> js_html = self.session.get(self.get_js_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> self.tk = self.get_tk(js_html)<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(js_html, **debug_lang_kwargs)<br /><br /> self.api_headers.update({<br /> "app-name": "xy",<br /> "device-id": "",<br /> "os-type": "web",<br /> "os-version": "",<br /> "version": "1.8.0",<br /> "X-Authorization": self.tk,<br /> })<br /> jwt_r = self.session.post(self.get_jwt_url, json=self.browser_data, headers=self.api_headers,<br /> timeout=timeout, proxies=proxies)<br /> self.jwt = jwt_r.json()['jwt']<br /> self.api_headers.update({"T-Authorization": self.jwt})<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> payload = {<br /> "cached": "true",<br /> "dict": "true",<br /> "media": "text",<br /> "os_type": "web",<br /> "replaced": "true",<br /> "request_id": "web_fanyi",<br /> "source": query_text.split('\n'),<br /> "trans_type": f"{from_language}2{to_language}",<br /> "browser_id": self.browser_data['browser_id'],<br /> }<br /><br /> if from_language == 'auto':<br /> payload.update({'detect': 'true'})<br /> if use_domain:<br /> payload.update({"dict_name": use_domain, "use_common_dict": "true"})<br /><br /> _ = self.session.options(self.api_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> r = self.session.post(self.api_url, headers=self.api_headers, json=payload, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else '\n'.join([self.decrypt(item) for item in data['target']])<br /><br /><br />class Deepl(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://www.deepl.com/translator'<br /> self.api_url = 'https://www2.deepl.com/jsonrpc'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_ajax_for_api=False, if_json_for_api=True)<br /> self.params = {'split': {'method': 'LMT_split_text'}, 'handle': {'method': 'LMT_handle_jobs'}}<br /> self.request_id = int(random.randrange(100, 10000) * 10000 + 4)<br /> self.language_map = None<br /> self.session = None<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, host_html: str, **kwargs: LangMapKwargsType) -> dict:<br /> lang_list = list(set(re.compile('translateIntoLang\\.(\\w+)":').findall(host_html)))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> def split_sentences_param(self, query_text: str, from_language: str) -> dict:<br /> data = {<br /> 'id': self.request_id,<br /> 'jsonrpc': '2.0',<br /> 'params': {<br /> 'texts': query_text.split('\n'),<br /> 'commonJobParams': {'mode': 'translate'},<br /> 'lang': {<br /> 'lang_user_selected': from_language,<br /> 'preference': {<br /> 'weight': {},<br /> 'default': 'default',<br /> },<br /> },<br /> },<br /> }<br /> return {**self.params['split'], **data}<br /><br /> def context_sentences_param(self, sentences: List[str], from_language: str, to_language: str) -> dict:<br /> sentences = [''] + sentences + ['']<br /> data = {<br /> 'id': self.request_id + 1,<br /> 'jsonrpc': ' 2.0',<br /> 'params': {<br /> 'priority': 1, # -1 if 'quality': 'fast'<br /> 'timestamp': self.get_timestamp(),<br /> 'commonJobParams': {<br /> # 'regionalVariant': 'en-US',<br /> 'browserType': 1,<br /> 'mode': 'translate',<br /> },<br /> 'jobs': [<br /> {<br /> 'kind': 'default',<br /> # 'quality': 'fast', # -1<br /> 'sentences': [{'id': i - 1, 'prefix': '', 'text': sentences[i]}],<br /> 'raw_en_context_before': sentences[1:i] if sentences[i - 1] else [],<br /> 'raw_en_context_after': [sentences[i + 1]] if sentences[i + 1] else [],<br /> 'preferred_num_beams': 1 if len(sentences) >= 4 else 4, # 1 if two sentences else 4, len>=2+2<br /> } for i in range(1, len(sentences) - 1)<br /> ],<br /> 'lang': {<br /> 'preference': {<br /> 'weight': {},<br /> 'default': 'default',<br /> },<br /> 'source_lang_user_selected': from_language, # "source_lang_computed"<br /> 'target_lang': to_language,<br /> },<br /> },<br /> }<br /> return {**self.params['handle'], **data}<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def deepl_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://www.deepl.com<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(host_html, **debug_lang_kwargs)<br /><br /> from_language, to_language = self.check_language(from_language, to_language, language_map=self.language_map,<br /> output_zh=self.output_zh, output_auto='auto')<br /> from_language = from_language.upper() if from_language != 'auto' else from_language<br /> to_language = to_language.upper() if to_language != 'auto' else to_language<br /><br /> ssp_data = self.split_sentences_param(query_text, from_language)<br /> r_s = self.session.post(self.api_url, params=self.params['split'], json=ssp_data, headers=self.api_headers,<br /> timeout=timeout, proxies=proxies)<br /> r_s.raise_for_status()<br /> s_data = r_s.json()<br /><br /> s_sentences = [it['sentences'][0]['text'] for item in s_data['result']['texts'] for it in item['chunks']]<br /> h_data = self.context_sentences_param(s_sentences, from_language, to_language)<br /><br /> r_cs = self.session.post(self.api_url, params=self.params['handle'], json=h_data, headers=self.api_headers,<br /> timeout=timeout, proxies=proxies)<br /> r_cs.raise_for_status()<br /> data = r_cs.json()<br /> time.sleep(sleep_seconds)<br /> self.request_id += 3<br /> self.query_count += 1<br /> return data if is_detail_result else '\n'.join(<br /> item['beams'][0]['sentences'][0]["text"] for item in data['result']['translations'])<br /><br /><br />class Yandex(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.home_url = 'https://yandex.com'<br /> self.host_url = 'https://translate.yandex.com'<br /> self.api_url = 'https://translate.yandex.net/api/v1/tr.json/translate'<br /> self.api_host = 'https://translate.yandex.net'<br /> self.detect_language_url = 'https://translate.yandex.net/api/v1/tr.json/detect'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True)<br /> self.api_headers.update({'Referer': self.api_host, 'x-retpath-y': self.host_url})<br /> self.language_map = None<br /> self.session = None<br /> self.sid = None<br /> self.yu = None<br /> self.yum = None<br /> self.sprvk = None<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(1e4) # ten thousand.<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, host_html: str, **kwargs: LangMapKwargsType) -> dict:<br /> lang_str = re.compile('TRANSLATOR_LANGS: {(.*?)},').search(host_html).group(0)[18:-1]<br /> lang_dict = json.loads(lang_str)<br /> lang_list = sorted(list(lang_dict.keys()))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> def get_yum(self) -> str:<br /> return str(int(time.time() * 1e10))<br /><br /> # def get_csrf_token(self, host_html: str) -> str:<br /> # return re.compile(pattern="CSRF_TOKEN: '(.*?)',").findall(host_html)[0]<br /> #<br /> # def get_key(self, host_html: str) -> str:<br /> # return re.compile(pattern="SPEECHKIT_KEY: '(.*?)',").findall(host_html)[0]<br /><br /> def get_sid(self, host_html: str) -> str:<br /> try:<br /> sid_find = re.compile("SID: '(.*?)',").findall(host_html)[0]<br /> return '.'.join([w[::-1] for w in sid_find.split('.')])<br /> except Exception as e:<br /> captcha_info = 'SmartCaptcha needs verification'<br /> if captcha_info in host_html:<br /> raise TranslatorError(captcha_info)<br /> raise TranslatorError(str(e))<br /><br /> def detect_language(self, ss: SessionType, query_text: str, sid: str, yu: str, headers: dict, timeout: float,<br /> proxies: dict) -> str:<br /> params = {<br /> 'sid': sid,<br /> 'yu': yu,<br /> 'text': query_text,<br /> 'srv': 'tr-text',<br /> 'hint': 'en,ru',<br /> 'options': 1<br /> }<br /> r = ss.get(self.detect_language_url, params=params, headers=headers, timeout=timeout, proxies=proxies)<br /> lang = r.json().get('lang')<br /> return lang if lang else 'en'<br /><br /> @Tse.uncertified<br /> @Tse.time_stat<br /> @Tse.check_query<br /> def yandex_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://translate.yandex.com<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param reset_host_url: str, default None. eg: 'https://translate.yandex.fr'<br /> :param if_check_reset_host_url: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> reset_host_url = kwargs.get('reset_host_url', None)<br /> if reset_host_url and reset_host_url != self.host_url:<br /> if kwargs.get('if_check_reset_host_url', True) and not reset_host_url[:25] == 'https://translate.yandex.':<br /> raise TranslatorError<br /> self.host_url = reset_host_url.strip('/')<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (<br /> self.session and self.language_map and not_update_cond_freq and not_update_cond_time and self.sid and self.yu):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.home_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /><br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(host_html, **debug_lang_kwargs)<br /><br /> self.sid = self.get_sid(host_html)<br /> self.yum = self.get_yum()<br /> self.yu = self.session.cookies.get_dict().get(<br /> 'yuidss') or f'{random.randint(int(1e8), int(9e8))}{int(time.time())}'<br /> self.sprvk = self.session.cookies.get_dict().get('spravka')<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /> if from_language == 'auto':<br /> from_language = self.detect_language(self.session, query_text, self.sid, self.yu, self.api_headers, timeout,<br /> proxies)<br /><br /> params = {<br /> 'id': f'{self.sid}-{self.query_count}-0',<br /> 'source_lang': from_language,<br /> 'target_lang': to_language,<br /> 'srv': 'tr-text',<br /> 'reason': 'paste', # 'auto'<br /> 'format': 'text',<br /> 'ajax': 1,<br /> 'yu': self.yu,<br /> }<br /> if self.sprvk:<br /> params.update({'sprvk': self.sprvk, 'yum': self.yum})<br /><br /> payload = urllib.parse.urlencode({'text': query_text, 'options': 4})<br /> r = self.session.post(self.api_url, params=params, data=payload, headers=self.api_headers, timeout=timeout,<br /> proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else '\n'.join(data['text'])<br /><br /><br />class Argos(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://translate.argosopentech.com'<br /> self.api_url = f'{self.host_url}/translate'<br /> self.language_url = f'{self.host_url}/languages'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False, if_ajax_for_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_ajax_for_api=False, if_json_for_api=True)<br /> self.language_headers = self.get_headers(self.host_url, if_api=False, if_json_for_api=True)<br /> self.host_pool = ['https://translate.argosopentech.com', 'https://libretranslate.de',<br /> 'https://translate.astian.org', 'https://translate.mentality.rip',<br /> 'https://translate.api.skitzen.com', 'https://trans.zillyhuhn.com']<br /> self.language_map = None<br /> self.session = None<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(5e3) # unknown<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_url: str, ss: SessionType, headers: dict, timeout: Optional[float],<br /> proxies: Optional[dict], **kwargs: LangMapKwargsType) -> dict:<br /> lang_list = ss.get(lang_url, headers=headers, timeout=timeout, proxies=proxies).json()<br /> lang_list = sorted([lang['code'] for lang in lang_list])<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def argos_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://translate.argosopentech.com<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param reset_host_url: str, default None.<br /> :return: str or dict<br /> """<br /><br /> reset_host_url = kwargs.get('reset_host_url', None)<br /> if reset_host_url and reset_host_url != self.host_url:<br /> if reset_host_url not in self.host_pool:<br /> raise TranslatorError<br /> self.host_url = reset_host_url<br /> self.api_url = f'{self.host_url}/translate'<br /> self.language_url = f'{self.host_url}/languages'<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies).text<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.language_url, self.session, self.language_headers, timeout,<br /> proxies, **debug_lang_kwargs)<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /> payload = {'q': query_text, 'source': from_language, 'target': to_language, 'format': 'text'}<br /> r = self.session.post(self.api_url, headers=self.api_headers, json=payload, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['translatedText']<br /><br /><br />class Iciba(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://www.iciba.com/fy'<br /> self.api_url = 'https://ifanyi.iciba.com/index.php'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False, if_ajax_for_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_ajax_for_api=True, if_json_for_api=False)<br /> self.language_headers = self.get_headers(self.host_url, if_api=False, if_json_for_api=True)<br /> self.language_map = None<br /> self.session = None<br /> self.s_y2 = 'ifanyiweb8hc9s98e'<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(3e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, api_url: str, ss: SessionType, headers: dict, timeout: Optional[float],<br /> proxies: Optional[dict], **kwargs: LangMapKwargsType) -> dict:<br /> params = {'c': 'trans', 'm': 'getLanguage', 'q': 0, 'type': 'en', 'str': ''}<br /> dd = ss.get(api_url, params=params, headers=headers, timeout=timeout, proxies=proxies).json()<br /> lang_list = sorted(list(set([lang for d in dd for lang in dd[d]])))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def iciba_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://www.iciba.com/fy<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.api_url, self.session, self.language_headers, timeout,<br /> proxies, **debug_lang_kwargs)<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> sign = hashlib.md5(f"6key_web_fanyi{self.s_y2}{query_text}".encode()).hexdigest()[:16] # strip()<br /> params = {'c': 'trans', 'm': 'fy', 'client': 6, 'auth_user': 'key_web_fanyi', 'sign': sign}<br /> payload = {'from': from_language, 'to': to_language, 'q': query_text}<br /> r = self.session.post(self.api_url, headers=self.api_headers, params=params, data=payload, timeout=timeout,<br /> proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['content'] if data.get('isSensitive') == 1 else data['content']['out']<br /><br /><br />class IflytekV1(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://saas.xfyun.cn/translate?tabKey=text'<br /> self.api_url = 'https://saas.xfyun.cn/ai-application/trans/its'<br /> self.language_old_url = 'https://saas.xfyun.cn/_next/static/4bzLSGCWUNl67Xal-AfIl/pages/translate.js'<br /> self.language_url_pattern = '/_next/static/(\w+([-]?\w+))/pages/translate.js'<br /> self.language_url = None<br /> self.cookies_url = 'https://sso.xfyun.cn//SSOService/login/getcookies'<br /> self.info_url = 'https://saas.xfyun.cn/ai-application/user/info'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True)<br /> self.language_map = None<br /> self.session = None<br /> self.query_count = 0<br /> self.output_zh = 'cn'<br /> self.input_limit = int(2e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, host_html: str, ss: SessionType, headers: dict, timeout: Optional[float],<br /> proxies: Optional[dict], **kwargs: LangMapKwargsType) -> dict:<br /> try:<br /> if not self.language_url:<br /> url_path = re.compile(self.language_url_pattern).search(host_html).group()<br /> self.language_url = f'{self.host_url[:21]}{url_path}'<br /> r = ss.get(self.language_url, headers=headers, timeout=timeout, proxies=proxies)<br /> except:<br /> r = ss.get(self.language_old_url, headers=headers, timeout=timeout, proxies=proxies)<br /><br /> js_html = r.text<br /> lang_str = re.compile('languageList:\\(e={(.*?)}').search(js_html).group()[16:]<br /> lang_list = sorted(list(execjs.eval(lang_str).keys()))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> @Tse.uncertified<br /> @Tse.time_stat<br /> @Tse.check_query<br /> def iflytek_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://saas.xfyun.cn/translate?tabKey=text<br /> :param query_text: str, must.<br /> :param from_language: str, default 'zh', unsupported 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> _ = self.session.get(self.cookies_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> _ = self.session.get(self.info_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(host_html, self.session, self.host_headers, timeout, proxies,<br /> **debug_lang_kwargs)<br /><br /> if from_language == 'auto':<br /> from_language = self.warning_auto_lang('iflytek', self.default_from_language, if_print_warning)<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> # cipher_query_text = base64.b64encode(query_text.encode()).decode()<br /> cipher_query_text = query_text<br /> payload = {'from': from_language, 'to': to_language, 'text': cipher_query_text}<br /> r = self.session.post(self.api_url, headers=self.api_headers, data=payload, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else json.loads(data['data'])['trans_result']['dst']<br /><br /><br />class IflytekV2(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://fanyi.xfyun.cn/console/trans/text' # https://www.iflyrec.com/html/translate.html<br /> self.api_url = 'https://fanyi.xfyun.cn/api-tran/trans/its'<br /> self.detect_language_url = 'https://fanyi.xfyun.cn/api-tran/trans/detection'<br /> self.language_url_pattern = '/js/trans-text/index.(.*?).js'<br /> self.language_url = None<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True)<br /> self.language_map = None<br /> self.session = None<br /> self.query_count = 0<br /> self.output_zh = 'cn'<br /> self.input_limit = int(2e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, host_html: str, ss: SessionType, headers: dict, timeout: Optional[float],<br /> proxies: Optional[dict], **kwargs: LangMapKwargsType) -> dict:<br /> host_true_url = f'https://{urllib.parse.urlparse(self.host_url).hostname}'<br /><br /> et = lxml.etree.HTML(host_html)<br /> host_js_url = f"""{host_true_url}{et.xpath('//script[@type="module"]/@src')[0]}"""<br /> host_js_html = ss.get(host_js_url, headers=headers, timeout=timeout, proxies=proxies).text<br /> self.language_url = f"""{host_true_url}{re.compile(self.language_url_pattern).search(host_js_html).group()}"""<br /><br /> lang_js_html = ss.get(self.language_url, headers=headers, timeout=timeout, proxies=proxies).text<br /> lang_list = re.compile('languageCode:"(.*?)",').findall(lang_js_html)<br /> lang_list = sorted(list(set(lang_list)))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> @Tse.uncertified<br /> @Tse.time_stat<br /> @Tse.check_query<br /> def iflytek_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://fanyi.xfyun.cn/console/trans/text<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(host_html, self.session, self.host_headers, timeout, proxies,<br /> **debug_lang_kwargs)<br /><br /> if from_language == 'auto':<br /> params = {'text': query_text}<br /> detect_r = self.session.get(self.detect_language_url, params=params, headers=self.host_headers,<br /> timeout=timeout, proxies=proxies)<br /> from_language = detect_r.json()[<br /> 'data'] if detect_r.status_code == 200 and detect_r.text.strip() != '' else self.output_zh<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> payload = {'from': from_language, 'to': to_language, 'text': query_text}<br /> r = self.session.post(self.api_url, headers=self.api_headers, data=payload, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else json.loads(data['data'])['trans_result']['dst']<br /><br /><br />class Iflyrec(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://fanyi.iflyrec.com'<br /> self.api_url = 'https://fanyi.iflyrec.com/TranslationService/v1/textAutoTranslation'<br /> self.detect_lang_url = 'https://fanyi.iflyrec.com/TranslationService/v1/languageDetection'<br /> self.language_url = 'https://fanyi.iflyrec.com/TranslationService/v1/textTranslation/languages'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_json_for_api=True)<br /> self.lang_index = {'zh': 1, 'en': 2, 'ja': 3, 'ko': 4, 'ru': 5, 'fr': 6, 'es': 7, 'vi': 8, 'yue': 9, 'ar': 12,<br /> 'de': 13, 'it': 14}<br /> self.lang_index_mirror = {v: k for k, v in self.lang_index.items()}<br /> self.language_map = None<br /> self.session = None<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(2e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_index: dict, **kwargs: LangMapKwargsType) -> dict:<br /> lang_list = sorted(list(lang_index.keys()))<br /> lang_map = {lang: ['zh'] for lang in lang_list if lang != 'zh'}<br /> return {**lang_map, **{'zh': lang_list}}<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def iflyrec_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://fanyi.iflyrec.com<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.lang_index, **debug_lang_kwargs)<br /><br /> if from_language == 'auto':<br /> params = {'t': self.get_timestamp()}<br /> form = {'originalText': query_text}<br /> detect_r = self.session.post(self.detect_lang_url, params=params, json=form, headers=self.api_headers,<br /> timeout=timeout, proxies=proxies)<br /> from_language_id = detect_r.json()['biz'][0]['detectionLanguage']<br /> from_language = self.lang_index_mirror[from_language_id]<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> api_params = {'t': self.get_timestamp()}<br /> api_form = {<br /> 'from': self.lang_index[from_language],<br /> 'to': self.lang_index[to_language],<br /> 'openTerminology': 'false',<br /> 'contents': [{'text': t.strip(), 'frontBlankLine': 0} for t in query_text.split('\n') if t.strip() != ''],<br /> }<br /> r = self.session.post(self.api_url, params=api_params, json=api_form, headers=self.api_headers, timeout=timeout,<br /> proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else '\n'.join([item['translateResult'] for item in data['biz']])<br /><br /><br />class Reverso(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://www.reverso.net/text-translation'<br /> self.api_url = 'https://api.reverso.net/translate/v1/translation'<br /> self.language_url = None<br /> self.language_pattern = 'https://cdn.reverso.net/trans/v(\\d).(\\d).(\\d)/main.js'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_json_for_api=True)<br /> self.session = None<br /> self.language_map = None<br /> self.decrypt_language_map = None<br /> self.query_count = 0<br /> self.output_zh = 'zh' # 'chi', because there are self.language_tran<br /> self.input_limit = int(2e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_html: str, **kwargs: LangMapKwargsType) -> dict:<br /> lang_dict_str = re.compile('={eng:(.*?)}').search(lang_html).group()[1:]<br /> lang_dict = execjs.eval(lang_dict_str)<br /> lang_list = sorted(list(lang_dict.values()))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> def decrypt_lang_map(self, lang_html: str) -> dict:<br /> lang_dict_str = re.compile('={eng:(.*?)}').search(lang_html).group()[1:]<br /> lang_dict = execjs.eval(lang_dict_str)<br /> return {k: v for v, k in lang_dict.items()}<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def reverso_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://www.reverso.net/text-translation<br /> :param query_text: str, must.<br /> :param from_language: str, default 'zh', unsupported 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (<br /> self.session and self.language_map and not_update_cond_freq and not_update_cond_time and self.decrypt_language_map):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> self.language_url = re.compile(self.language_pattern).search(host_html).group()<br /> lang_html = self.session.get(self.language_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> self.decrypt_language_map = self.decrypt_lang_map(lang_html)<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(lang_html, **debug_lang_kwargs)<br /><br /> if from_language == 'auto':<br /> from_language = self.warning_auto_lang('reverso', self.default_from_language, if_print_warning)<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /> from_language, to_language = self.decrypt_language_map[from_language], self.decrypt_language_map[to_language]<br /><br /> payload = {<br /> 'format': 'text',<br /> 'from': from_language,<br /> 'to': to_language,<br /> 'input': query_text,<br /> 'options': {<br /> 'contextResults': 'true',<br /> 'languageDetection': 'true',<br /> 'sentenceSplitter': 'true',<br /> 'origin': 'translation.web',<br /> }<br /> }<br /> r = self.session.post(self.api_url, json=payload, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else ''.join(data['translation'])<br /><br /><br />class Itranslate(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://itranslate.com/translate'<br /> self.api_url = 'https://web-api.itranslateapp.com/v3/texts/translate'<br /> self.manifest_url = 'https://itranslate-webapp-production.web.app/manifest.json'<br /> self.language_url = None<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_json_for_api=True)<br /> self.session = None<br /> self.language_map = None<br /> self.api_key = None<br /> self.query_count = 0<br /> self.output_zh = 'zh-CN'<br /> self.input_limit = int(1e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_html: str, **kwargs: LangMapKwargsType) -> dict:<br /> lang_str = re.compile('\\[{dialect:"auto",(.*?)}]').search(lang_html).group()<br /> lang_origin_list = execjs.eval(lang_str)<br /> lang_list = sorted(list(set([dd['dialect'] for dd in lang_origin_list])))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> def get_apikey(self, lang_html: str) -> str:<br /> return re.compile('"API-KEY":"(.*?)"').findall(lang_html)[0]<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def itranslate_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://itranslate.com/translate<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /><br /> if not self.language_url:<br /> manifest_data = self.session.get(self.manifest_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).json()<br /> self.language_url = manifest_data.get('main.js')<br /><br /> lang_html = self.session.get(self.language_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(lang_html, **debug_lang_kwargs)<br /><br /> self.api_key = self.get_apikey(lang_html)<br /> self.api_headers.update({'API-KEY': self.api_key})<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh,<br /> output_en_translator='itranslate', output_en='en-US')<br /><br /> payload = {<br /> 'source': {'dialect': from_language, 'text': query_text, 'with': ['synonyms']},<br /> 'target': {'dialect': to_language},<br /> }<br /> r = self.session.post(self.api_url, headers=self.api_headers, json=payload, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['target']['text']<br /><br /><br />class TranslateCom(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://www.translate.com/machine-translation'<br /> self.api_url = 'https://www.translate.com/translator/translate_mt'<br /> self.lang_detect_url = 'https://www.translate.com/translator/ajax_lang_auto_detect'<br /> self.language_url = 'https://www.translate.com/ajax/language/ht/all'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_json_for_api=False)<br /> self.session = None<br /> self.language_map = None<br /> self.language_description = None<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(1.5e4) # fifteen thousand letters left today.<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_desc: dict, **kwargs: LangMapKwargsType) -> dict:<br /> return {item['code']: [it['code'] for it in item['availableTranslationLanguages']] for item in lang_desc}<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def translateCom_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://www.translate.com/machine-translation<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> lang_r = self.session.get(self.language_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> self.language_description = lang_r.json()<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.language_description, **debug_lang_kwargs)<br /><br /> if from_language == 'auto':<br /> detect_form = {'text_to_translate': query_text}<br /> r_detect = self.session.post(self.lang_detect_url, data=detect_form, headers=self.api_headers,<br /> timeout=timeout, proxies=proxies)<br /> from_language = r_detect.json()['language']<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> payload = {<br /> 'text_to_translate': query_text,<br /> 'source_lang': from_language,<br /> 'translated_lang': to_language,<br /> 'use_cache_only': 'false',<br /> }<br /> r = self.session.post(self.api_url, data=payload, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['translated_text'] # translation_source is microsoft, wtf!<br /><br /><br />class Utibet(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'http://mt.utibet.edu.cn/mt' # must http<br /> self.api_url = self.host_url<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_json_for_api=False)<br /> self.language_map = {'ti': ['zh'], 'zh': ['ti']}<br /> self.session = None<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(5e3) # unknown<br /> self.default_from_language = self.output_zh<br /><br /> def parse_result(self, host_html: str) -> str:<br /> et = lxml.etree.HTML(host_html)<br /> return et.xpath('//*[@name="tgt"]/text()')[0]<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def utibet_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'ti',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> http://mt.utibet.edu.cn/mt<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto', equals to 'zh'.<br /> :param to_language: str, default 'ti'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /><br /> if from_language == 'auto':<br /> from_language = self.warning_auto_lang('utibet', self.default_from_language, if_print_warning)<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /> payload = {<br /> 'src': query_text,<br /> 'tgt': query_text if from_language == 'ti' else '',<br /> 'lang': 'tc' if from_language == 'ti' else 'ct',<br /> }<br /> payload = urllib.parse.urlencode(payload)<br /> r = self.session.post(self.api_url, headers=self.api_headers, data=payload, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data_html = r.text<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return {'data_html': data_html} if is_detail_result else self.parse_result(data_html)<br /><br /><br />class Papago(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://papago.naver.com'<br /> self.api_url = 'https://papago.naver.com/apis/n2mt/translate' # nsmt<br /> self.web_api_url = 'https://papago.naver.net/website'<br /> self.lang_detect_url = 'https://papago.naver.com/apis/langs/dect'<br /> self.language_url = None<br /> self.language_url_pattern = '/home.(.*?).chunk.js'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_json_for_api=False)<br /> self.language_map = None<br /> self.session = None<br /> self.device_id = None<br /> self.auth_key = None # 'v1.7.1_12f919c9b5' #'v1.6.7_cc60b67557'<br /> self.query_count = 0<br /> self.output_zh = 'zh-CN'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_html: str, **kwargs: LangMapKwargsType) -> dict:<br /> lang_str = re.compile('={ALL:(.*?)}').search(lang_html).group()[1:]<br /> lang_str = lang_str.lower().replace('zh-cn', 'zh-CN').replace('zh-tw', 'zh-TW')<br /> lang_list = re.compile(',"(.*?)":|,(.*?):').findall(lang_str)<br /> lang_list = [j if j else k for j, k in lang_list]<br /> lang_list = sorted(list(filter(lambda x: x not in ('all', 'auto'), lang_list)))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> def get_auth_key(self, lang_html: str) -> str:<br /> return re.compile('AUTH_KEY:"(.*?)"').findall(lang_html)[0]<br /><br /> def get_authorization(self, url: str, auth_key: str, device_id: str, timestamp: int) -> str:<br /> auth = hmac.new(key=auth_key.encode(), msg=f'{device_id}\n{url}\n{timestamp}'.encode(),<br /> digestmod='md5').digest()<br /> return f'PPG {device_id}:{base64.b64encode(auth).decode()}'<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def papago_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://papago.naver.com<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time and self.auth_key):<br /> self.device_id = str(uuid.uuid4())<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> url_path = re.compile(self.language_url_pattern).search(host_html).group()<br /> self.language_url = ''.join([self.host_url, url_path])<br /> lang_html = self.session.get(self.language_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(lang_html, **debug_lang_kwargs)<br /> self.auth_key = self.get_auth_key(lang_html)<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> detect_time = self.get_timestamp()<br /> detect_auth = self.get_authorization(self.lang_detect_url, self.auth_key, self.device_id, detect_time)<br /> detect_add_headers = {'device-type': 'pc', 'timestamp': str(detect_time), 'authorization': detect_auth}<br /> detect_headers = {**self.api_headers, **detect_add_headers}<br /><br /> if from_language == 'auto':<br /> detect_form = urllib.parse.urlencode({'query': query_text})<br /> r_detect = self.session.post(self.lang_detect_url, headers=detect_headers, data=detect_form,<br /> timeout=timeout, proxies=proxies)<br /> from_language = r_detect.json()['langCode']<br /><br /> trans_time = self.get_timestamp()<br /> trans_auth = self.get_authorization(self.api_url, self.auth_key, self.device_id, trans_time)<br /> trans_update_headers = {'x-apigw-partnerid': 'papago', 'timestamp': str(trans_time),<br /> 'authorization': trans_auth}<br /> detect_headers.update(trans_update_headers)<br /> trans_headers = detect_headers<br /><br /> payload = {<br /> 'deviceId': self.device_id,<br /> 'text': query_text, 'source': from_language, 'target': to_language, 'locale': 'en',<br /> 'dict': 'true', 'dictDisplay': 30, 'honorific': 'false', 'instant': 'false', 'paging': 'false',<br /> }<br /> payload = urllib.parse.urlencode(payload)<br /> r = self.session.post(self.api_url, headers=trans_headers, data=payload, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['translatedText']<br /><br /><br />class Lingvanex(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://lingvanex.com/demo/'<br /> self.api_url = None<br /> self.language_url = None<br /> self.auth_url = 'https://lingvanex.com/lingvanex_demo_page/js/api-base.js'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_json_for_api=False)<br /> self.session = None<br /> self.language_map = None<br /> self.detail_language_map = None<br /> self.auth_info = None<br /> self.mode = None<br /> self.model_pool = ('B2B', 'B2C',)<br /> self.query_count = 0<br /> self.output_zh = 'zh-Hans_CN'<br /> self.input_limit = int(1e4)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_url: str, ss: SessionType, headers: dict, timeout: Optional[float],<br /> proxies: Optional[dict], **kwargs: LangMapKwargsType) -> dict:<br /> params = {'all': 'true', 'code': 'en_GB', 'platform': 'dp', '_': self.get_timestamp()}<br /> detail_lang_map = ss.get(lang_url, params=params, headers=headers, timeout=timeout, proxies=proxies).json()<br /> for _ in range(3):<br /> _ = ss.get(lang_url, params={'platform': 'dp'}, headers=headers, timeout=timeout, proxies=proxies)<br /> lang_list = sorted(set([item['full_code'] for item in detail_lang_map['result']]))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> def get_d_lang_map(self, lang_url: str, ss: SessionType, headers: dict, timeout: float, proxies: dict) -> dict:<br /> params = {'all': 'true', 'code': 'en_GB', 'platform': 'dp', '_': self.get_timestamp()}<br /> return ss.get(lang_url, params=params, headers=headers, timeout=timeout, proxies=proxies).json()<br /><br /> def get_auth(self, auth_url: str, ss: SessionType, headers: dict, timeout: float, proxies: dict) -> dict:<br /> js_html = ss.get(auth_url, headers=headers, timeout=timeout, proxies=proxies).text<br /> return {k: v for k, v in re.compile(',(.*?)="(.*?)"').findall(js_html)}<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def lingvanex_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://lingvanex.com/demo/<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param lingvanex_mode: str, default "B2C", choose from ("B2B", "B2C").<br /> :return: str or dict<br /> """<br /><br /> mode = kwargs.get('lingvanex_mode', 'B2C')<br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (<br /> self.session and self.language_map and not_update_cond_freq and not_update_cond_time and self.auth_info and self.mode == mode):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> self.auth_info = self.get_auth(self.auth_url, self.session, self.host_headers, timeout, proxies)<br /><br /> if mode not in self.model_pool:<br /> raise TranslatorError<br /><br /> if mode != self.mode:<br /> self.mode = mode<br /> self.api_url = ''.join([self.auth_info[f'{mode}_BASE_URL'], self.auth_info['TRANSLATE_URL']])<br /> self.language_url = ''.join([self.auth_info[f'{mode}_BASE_URL'], self.auth_info['GET_LANGUAGES_URL']])<br /> self.host_headers.update({'authorization': self.auth_info[f'{mode}_AUTH_TOKEN']})<br /> self.api_headers.update({'authorization': self.auth_info[f'{mode}_AUTH_TOKEN']})<br /> self.api_headers.update({'referer': urllib.parse.urlparse(self.auth_info[f'{mode}_BASE_URL']).netloc})<br /><br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.language_url, self.session, self.host_headers, timeout,<br /> proxies, **debug_lang_kwargs)<br /> self.detail_language_map = self.get_d_lang_map(self.language_url, self.session, self.host_headers, timeout,<br /> proxies)<br /><br /> if from_language == 'auto':<br /> from_language = self.warning_auto_lang('lingvanex', self.default_from_language, if_print_warning)<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh,<br /> output_en_translator='lingvanex', output_en='en_GB')<br /><br /> payload = {<br /> 'from': from_language,<br /> 'to': to_language,<br /> 'text': query_text,<br /> 'platform': 'dp',<br /> 'is_return_text_split_ranges': 'true'<br /> }<br /> payload = urllib.parse.urlencode(payload)<br /> r = self.session.post(self.api_url, data=payload, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['result']['text']<br /><br /><br />class Mglip(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'http://fy.mglip.com/pc' # must http<br /> self.api_url = 'http://fy.mglip.com/t2t'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_json_for_api=False)<br /> self.language_map = {}.fromkeys(['zh', 'mon', 'xle'], ['zh', 'mon', 'xle'])<br /> self.session = None<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(5e2)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def mglip_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'mon',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> http://fy.mglip.com/pc<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto', equals 'zh'.<br /> :param to_language: str, default 'mon'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /><br /> if from_language == 'auto':<br /> from_language = self.warning_auto_lang('mglip', self.default_from_language, if_print_warning)<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> payload = {'userInput': query_text, 'from': from_language, 'to': to_language}<br /> payload = urllib.parse.urlencode(payload)<br /> r = self.session.post(self.api_url, headers=self.api_headers, data=payload, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['datas'][0]['paragraph'] if data['datas'][0]['type'] == 'trans' else \<br /> data['datas'][0]['data']<br /><br /><br />class VolcEngine(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://translate.volcengine.com'<br /> self.api_url = 'https://translate.volcengine.com/web/translate/v1'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_json_for_api=True)<br /> self.session = None<br /> self.language_map = None<br /> self.ms_token = ''<br /> self.x_bogus = 'DFS#todo'<br /> self.signature = '_02B#todo'<br /> self.query_count = 0<br /> self.output_auto = 'detect'<br /> self.output_zh = 'zh'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, host_html: str, **kwargs: LangMapKwargsType) -> dict:<br /> lang_list = re.compile('"language_(.*?)":').findall(host_html)<br /> lang_list = sorted(list(set(lang_list)))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> @property<br /> def professional_field_map(self) -> dict:<br /> data = {<br /> '': {'category': '', 'glossary_list': []},<br /> 'clean': {'category': 'clean', 'glossary_list': []},<br /> 'novel': {'category': 'novel', 'glossary_list': []},<br /> 'finance': {'category': 'finance', 'glossary_list': []},<br /> 'biomedical': {'category': 'biomedical', 'glossary_list': []},<br /><br /> 'ai': {'category': '', 'glossary_list': ['ailab/ai']},<br /> 'menu': {'category': '', 'glossary_list': ['ailab/menu']},<br /> 'techfirm': {'category': '', 'glossary_list': ['ailab/techfirm']},<br /><br /> 'ecommerce': {'category': 'ecommerce', 'glossary_list': ['ailab/ecommerce']},<br /> 'technique': {'category': 'technique', 'glossary_list': ['ailab/technique']},<br /> }<br /> return data<br /><br /> @Tse.uncertified<br /> @Tse.time_stat<br /> @Tse.check_query<br /> def volcEngine_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://translate.volcengine.com<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param professional_field: str, default '', choose from ('', 'clean')<br /> :return: str or dict<br /> """<br /><br /> use_domain = kwargs.get('professional_field', '')<br /> if use_domain not in self.professional_field_map:<br /> raise TranslatorError<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(host_html, **debug_lang_kwargs)<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_auto=self.output_auto, output_zh=self.output_zh)<br /> params = {<br /> 'msToken': self.ms_token,<br /> 'X-Bogus': self.x_bogus,<br /> '_signature': self.signature,<br /> }<br /> payload = {<br /> 'text': query_text,<br /> 'source_language': from_language,<br /> 'target_language': to_language,<br /> 'home_language': 'zh',<br /> 'enable_user_glossary': 'false',<br /> }<br /> payload.update(self.professional_field_map[use_domain])<br /> r = self.session.post(self.api_url, params=params, json=payload, headers=self.api_headers, timeout=timeout,<br /> proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['translation']<br /><br /><br />class ModernMt(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://www.modernmt.com/translate'<br /> self.api_url = 'https://webapi.modernmt.com/translate'<br /> self.language_url = 'https://www.modernmt.com/scripts/app.bundle.js'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_json_for_api=True,<br /> if_http_override_for_api=True)<br /> self.session = None<br /> self.language_map = None<br /> self.query_count = 0<br /> self.output_zh = 'zh-CN'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_url: str, ss: SessionType, headers: dict, timeout: Optional[float],<br /> proxies: Optional[dict], **kwargs: LangMapKwargsType) -> dict:<br /> lang_html = ss.get(lang_url, headers=headers, timeout=timeout, proxies=proxies).text<br /> d_lang_map = json.loads(re.compile('''('{(.*?)}')''').search(lang_html).group(0)[1:-1])<br /> lang_list = sorted(d_lang_map.keys())<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def modernMt_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://www.modernmt.com/translate<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.language_url, self.session, self.host_headers, timeout,<br /> proxies, **debug_lang_kwargs)<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> timestamp = self.get_timestamp()<br /> payload = {<br /> 'q': query_text,<br /> 'source': '' if from_language == 'auto' else from_language,<br /> 'target': to_language,<br /> 'ts': timestamp,<br /> 'verify': hashlib.md5(f'webkey_E3sTuMjpP8Jez49GcYpDVH7r#{timestamp}#{query_text}'.encode()).hexdigest(),<br /> 'hints': '',<br /> 'multiline': 'true',<br /> }<br /> r = self.session.post(self.api_url, json=payload, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['data']['translation']<br /><br /><br />class MyMemory(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://mymemory.translated.net'<br /> self.api_web_url = 'https://mymemory.translated.net/api/ajaxfetch'<br /> self.api_api_url = 'https://api.mymemory.translated.net/get'<br /> self.get_matecat_language_url = 'https://www.matecat.com/api/v2/languages'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False)<br /> self.session = None<br /> self.language_map = None<br /> self.myMemory_language_list = None<br /> self.mateCat_language_list = None<br /> self.query_count = 0<br /> self.output_zh = 'zh-CN'<br /> self.input_limit = int(5e2)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, myMemory_host_html: str, matecat_lang_url: str, ss: SessionType, headers: dict,<br /> timeout: Optional[float], proxies: Optional[dict], **kwargs: LangMapKwargsType) -> dict:<br /> et = lxml.etree.HTML(myMemory_host_html)<br /> lang_list = et.xpath('//*[@id="select_source_mm"]/option/@value')[2:]<br /> self.myMemory_language_list = sorted(list(set(lang_list)))<br /><br /> lang_d_list = ss.get(matecat_lang_url, headers=headers, timeout=timeout, proxies=proxies).json()<br /> self.mateCat_language_list = sorted(list(set([item['code'] for item in lang_d_list])))<br /><br /> lang_list = sorted(list(set(self.myMemory_language_list + self.mateCat_language_list)))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def myMemory_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://mymemory.translated.net<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param myMemory_mode: str, default "web", choose from ("web", "api").<br /> :return: str or dict<br /> """<br /><br /> mode = kwargs.get('myMemory_mode', 'web')<br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(host_html, self.get_matecat_language_url, self.session,<br /> self.host_headers, timeout, proxies, **debug_lang_kwargs)<br /><br /> if from_language == 'auto':<br /> from_language = self.warning_auto_lang('myMemory', self.default_from_language, if_print_warning)<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh,<br /> output_en_translator='myMemory', output_en='en-GB')<br /><br /> params = {<br /> 'q': query_text,<br /> 'langpair': f'{from_language}|{to_language}'<br /> }<br /> params = params if mode == 'api' else {**params, **{'mtonly': 1}}<br /> api_url = self.api_api_url if mode == 'api' else self.api_web_url<br /><br /> r = self.session.get(api_url, params=params, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['responseData']['translatedText']<br /><br /><br />class Mirai(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.home_url = 'https://miraitranslate.com'<br /> self.host_url = 'https://miraitranslate.com/trial/'<br /> self.api_url = 'https://trial.miraitranslate.com/trial/api/translate.php'<br /> self.lang_url = None<br /> self.lang_url_pattern = 'main-es2015.(.*?).js'<br /> self.detect_lang_url = 'https://trial.miraitranslate.com/trial/api/detect_lang.php'<br /> self.trace_url = 'https://trial.miraitranslate.com/trial/api/trace.php'<br /> self.host_headers = self.get_headers(self.home_url, if_api=False)<br /> self.api_json_headers = self.get_headers(self.home_url, if_api=True, if_json_for_api=True)<br /> self.api_text_headers = self.get_headers(self.home_url, if_api=True, if_ajax_for_api=False)<br /> self.session = None<br /> self.language_map = None<br /> self.tran_key = None<br /> self.trans_id = str(uuid.uuid4())<br /> self.user_id = str(uuid.uuid4())<br /> self.lang_zh_map = {'zh-CN': 'zh', 'zh-TW': 'zt'}<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(2e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_url: str, ss: SessionType, headers: dict, timeout: Optional[float],<br /> proxies: Optional[dict], **kwargs: LangMapKwargsType) -> dict:<br /> js_html = ss.get(lang_url, headers=headers, timeout=timeout, proxies=proxies).text<br /> lang_pairs = re.compile('"/trial/(\\w{2})/(\\w{2})"').findall(js_html)<br /> return {f_lang: [v for k, v in lang_pairs if k == f_lang] for f_lang, t_lang in lang_pairs}<br /><br /> @Tse.uncertified<br /> @Tse.time_stat<br /> @Tse.check_query<br /> def mirai_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'ja',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://miraitranslate.com/en/trial/<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'ja'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time and self.tran_key):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> # _ = self.session.get(self.home_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> self.tran_key = re.compile('var tran = "(.*?)";').search(host_html).group(1)<br /> lang_url_part = re.compile(self.lang_url_pattern).search(host_html).group()<br /> self.lang_url = f'https://miraitranslate.com/trial/inmt/{lang_url_part}'<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.lang_url, self.session, self.api_json_headers, timeout,<br /> proxies, **debug_lang_kwargs)<br /><br /> if from_language == 'auto':<br /> r = self.session.post(self.detect_lang_url, headers=self.api_json_headers, json={'text': query_text},<br /> timeout=timeout, proxies=proxies)<br /> from_language = r.json()['language']<br /> from_language = self.lang_zh_map[from_language] if 'zh' in from_language else from_language<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /><br /> trace_data = {<br /> 'operationType': 'SLA',<br /> 'lang': from_language,<br /> 'source': query_text,<br /> 'userId': self.user_id,<br /> 'transId': self.trans_id,<br /> 'uniqueId': self.tran_key,<br /> 'date': f'{datetime.datetime.utcnow().isoformat()[:-3]}Z',<br /> }<br /> _ = self.session.post(self.trace_url, json=trace_data, headers=self.api_text_headers, timeout=timeout,<br /> proxies=proxies)<br /><br /> payload = {<br /> 'input': query_text,<br /> 'source': from_language,<br /> 'target': to_language,<br /> 'tran': self.tran_key,<br /> 'adaptPhrases': [],<br /> 'filter_profile': 'nmt',<br /> 'profile': 'inmt',<br /> 'usePrefix': 'false',<br /> 'zt': 'true' if 'zt' in (from_language, to_language) else 'false',<br /> 'InmtTarget': '',<br /> 'InmtTranslateType': 'gisting',<br /> }<br /> r = self.session.post(self.api_url, data=payload, headers=self.api_text_headers, timeout=timeout,<br /> proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['ouputs'][0]['output'][0]['translation']<br /><br /><br />class Apertium(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://www.apertium.org/'<br /> self.api_url = 'https://apertium.org/apy/translate'<br /> self.get_lang_url = 'https://www.apertium.org/index.js'<br /> self.detect_lang_url = 'https://apertium.org/apy/identifyLang'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False, if_referer_for_host=True)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True)<br /> self.session = None<br /> self.language_map = None<br /> self.query_count = 0<br /> self.output_zh = None # unsupported<br /> self.output_en = 'eng'<br /> self.input_limit = int(1e4) # almost no limit.<br /> self.default_from_language = 'spa'<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_url: str, ss: SessionType, headers: dict, timeout: Optional[float],<br /> proxies: Optional[dict], **kwargs: LangMapKwargsType) -> dict:<br /> js_html = ss.get(lang_url, headers=headers, timeout=timeout, proxies=proxies).text<br /> lang_pairs = re.compile('{sourceLanguage:"(.*?)",targetLanguage:"(.*?)"}').findall(js_html)<br /> return {f_lang: [v for k, v in lang_pairs if k == f_lang] for f_lang, t_lang in lang_pairs}<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def apertium_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://www.apertium.org/<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.get_lang_url, self.session, self.host_headers, timeout,<br /> proxies, **debug_lang_kwargs)<br /><br /> if from_language == 'auto':<br /> payload = urllib.parse.urlencode({'q': query_text})<br /> langs = self.session.post(self.detect_lang_url, data=payload, headers=self.api_headers, timeout=timeout,<br /> proxies=proxies).json()<br /> from_language = sorted(langs, key=lambda k: langs[k], reverse=True)[0]<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_en_translator='apertium', output_en=self.output_en)<br /><br /> payload = {<br /> 'q': query_text,<br /> 'langpair': f'{from_language}|{to_language}',<br /> 'prefs': '',<br /> 'markUnknown': 'no',<br /> }<br /> payload = urllib.parse.urlencode(payload)<br /> r = self.session.post(self.api_url, data=payload, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['responseData']['translatedText']<br /><br /><br />class Tilde(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://translate.tilde.com/'<br /> self.api_url = 'https://letsmt.eu/ws/service.svc/json/TranslateEx'<br /> self.get_config_url = 'https://translate.tilde.com/assets/config.local.json' # ?version=46852<br /> self.subscribe_url = 'https://translate.tilde.com/assets/subscriptions-config.local.json'<br /> self.plausible_url = 'https://plausible.io/api/event'<br /> self.auth_url = 'https://auth.tilde.com/auth/realms/Tilde/protocol/openid-connect/login-status-iframe.html/init'<br /> self.speech_url = 'https://va.tilde.com/dl/directline/aHR0cDovL3Byb2RrOHNib3R0aWxkZTQ=/tokens/speech'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False, if_referer_for_host=True)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_json_for_api=True)<br /> self.session = None<br /> self.language_map = None<br /> self.langpair_ids = None<br /> self.config_data = None<br /> self.sys_data = None<br /> self.query_count = 0<br /> self.output_zh = None # unsupported<br /> self.output_en = 'eng'<br /> self.input_limit = int(5e3) # unknown<br /> self.default_from_language = 'lv' # 'fr'<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, sys_data: dict, **kwargs: LangMapKwargsType) -> dict:<br /> lang_pairs = [[item['SourceLanguage']['Code'], item['TargetLanguage']['Code']] for item in sys_data['System'] if<br /> 'General' in item['Domain']]<br /> return {f_lang: [v for k, v in lang_pairs if k == f_lang] for f_lang, t_lang in lang_pairs}<br /><br /> def get_langpair_ids(self, sys_data: dict) -> dict:<br /> return {f"{item['SourceLanguage']['Code']}-{item['TargetLanguage']['Code']}": item['ID'] for item in<br /> sys_data['System'] if 'General' in item['Domain']}<br /><br /> @Tse.uncertified<br /> @Tse.time_stat<br /> @Tse.check_query<br /> def tilde_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://translate.tilde.com/<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> self.config_data = self.session.get(self.get_config_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).json()<br /> self.api_headers.update({'client-id': self.config_data['mt']['api']['clientId']}) # must lower keyword<br /><br /> sys_url = self.config_data['mt']['api']['systemListUrl']<br /> params = {'appID': self.config_data['mt']['api']['appID'],<br /> 'uiLanguageID': self.config_data['mt']['api']['uiLanguageID']}<br /> self.sys_data = self.session.get(sys_url, params=params, headers=self.api_headers, timeout=timeout,<br /> proxies=proxies).json() # test<br /> self.langpair_ids = self.get_langpair_ids(self.sys_data)<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.sys_data, **debug_lang_kwargs)<br /><br /> if from_language == 'auto':<br /> from_language = self.warning_auto_lang('tilde', self.default_from_language, if_print_warning)<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map)<br /><br /> payload = {<br /> 'text': query_text,<br /> 'appID': self.config_data['mt']['api']['appID'],<br /> 'systemID': self.langpair_ids[f'{from_language}-{to_language}'],<br /> 'options': 'widget=text,alignment,markSentences',<br /> }<br /> r = self.session.post(self.api_url, json=payload, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['translation']<br /><br /><br />class CloudYi(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.home_url = 'https://www.cloudtranslation.com'<br /> self.host_url = 'https://www.cloudtranslation.com/#/translate'<br /> self.api_url = 'https://www.cloudtranslation.com/official-website/v1/transOneSrcText'<br /> self.get_lang_url = 'https://online.cloudtranslation.com/api/v1.0/site/get_all_language_and_domain'<br /> self.detect_lang_url = 'https://online.cloudtranslation.com/api/v1.0/request_translate/langid'<br /> self.get_cookie_url = 'https://online.cloudtranslation.com/api/v1.0/site/sites_language_list'<br /> self.host_headers = self.get_headers(self.home_url, if_api=False, if_referer_for_host=True)<br /> self.api_headers = self.get_headers(self.home_url, if_api=True, if_json_for_api=True)<br /> self.session = None<br /> self.language_map = None<br /> self.langpair_domain = None<br /> self.professional_field = None<br /> self.query_count = 0<br /> self.output_zh = 'zh-cn'<br /> self.output_en = 'en-us'<br /> self.output_auto = 'all'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, d_lang_map: dict, **kwargs: LangMapKwargsType) -> dict:<br /> return {k: [it['language_code'] for it in item] for k, item in d_lang_map['data']['src_to_tgt'].items()}<br /><br /> def get_langpair_domain(self, d_lang_map: dict) -> dict:<br /> return {k: [it['domain_code'] for it in item] for k, item in<br /> d_lang_map['data']['language_pair_to_domain'].items()}<br /><br /> def get_professional_field_list(self, d_lang_map: dict) -> set:<br /> return {it['domain_code'] for _, item in d_lang_map['data']['language_pair_to_domain'].items() for it in item}<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def cloudYi_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://www.cloudtranslation.com/#/translate<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param professional_field: str, default 'general'.<br /> :return: str or dict<br /> """<br /><br /> use_domain = kwargs.get('professional_field', 'general')<br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> _ = self.session.get(self.get_cookie_url, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> d_lang_map = self.session.get(self.get_lang_url, headers=self.api_headers, timeout=timeout,<br /> proxies=proxies).json()<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(d_lang_map, **debug_lang_kwargs)<br /> self.langpair_domain = self.get_langpair_domain(d_lang_map)<br /> self.professional_field = self.get_professional_field_list(d_lang_map)<br /><br /> if from_language == 'auto':<br /> payload = {'text': query_text}<br /> r = self.session.post(self.detect_lang_url, json=payload, headers=self.api_headers, timeout=timeout,<br /> proxies=proxies)<br /> from_language = r.json()['data']['language']<br /> from_language, to_language = from_language.lower(), to_language.lower() # must lower<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh,<br /> output_en_translator='cloudYi', output_en=self.output_en)<br /><br /> domains = self.langpair_domain.get(f'{from_language}_{to_language}')<br /> if not domains:<br /> raise TranslatorError<br /> if use_domain not in domains:<br /> use_domain = domains[0]<br /><br /> payload = {<br /> 'text': query_text,<br /> 'domain': use_domain,<br /> 'srcLangCode': from_language,<br /> 'tgtLangCode': to_language,<br /> }<br /> r = self.session.post(self.api_url, json=payload, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['data']['translation']<br /><br /><br />class SysTran(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.home_url = 'https://www.systran.net'<br /> self.host_url = 'https://www.systran.net/translate/'<br /> self.api_url = 'https://api-translate.systran.net/translation/text/translate'<br /> self.get_lang_url = 'https://api-translate.systran.net/translation/supportedLanguages'<br /> self.get_token_url = 'https://translate.systran.net/oidc/token'<br /> self.get_client_url = 'https://www.systran.net/wp-content/themes/systran/translator/js/translateBox.bundle.js'<br /> self.host_headers = self.get_headers(self.home_url, if_api=False, if_referer_for_host=True)<br /> self.api_ajax_headers = self.get_headers(self.home_url, if_api=True, if_ajax_for_api=True)<br /> self.api_json_headers = self.get_headers(self.home_url, if_api=True, if_json_for_api=True)<br /> self.session = None<br /> self.language_map = None<br /> self.professional_field = None<br /> self.langpair_domain = None<br /> self.client_data = None<br /> self.token_data = None<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(5e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, d_lang_map: dict, **kwargs: LangMapKwargsType) -> dict:<br /> return {ii['source']: [jj['target'] for jj in d_lang_map['languagePairs'] if jj['source'] == ii['source']] for<br /> ii in d_lang_map['languagePairs']}<br /><br /> def get_professional_field_list(self, d_lang_map: dict) -> set:<br /> return {it['selectors']['domain'] for item in d_lang_map['languagePairs'] for it in item['profiles']}<br /><br /> def get_langpair_domain(self, d_lang_map: dict) -> dict:<br /> data = {<br /> f'{item["source"]}__{item["target"]}__{it["selectors"]["domain"]}': {<br /> 'domain': it["selectors"]["domain"],<br /> 'owner': it['selectors']['owner'],<br /> 'size': it['selectors']['size'],<br /> } for item in d_lang_map['languagePairs'] for it in item['profiles']<br /> }<br /> return data<br /><br /> def get_client_data(self, client_url: str, ss: SessionType, headers: dict, timeout: float, proxies: dict) -> dict:<br /> js_html = ss.get(client_url, headers=headers, timeout=timeout, proxies=proxies).text<br /> search_groups = re.compile('"https://translate.systran.net/oidc",\\w="(.*?)",\\w="(.*?)";').search(<br /> js_html) # \\w{1} == \\w<br /> client_data = {<br /> 'grant_type': 'client_credentials',<br /> 'client_id': search_groups.group(1),<br /> 'client_secret': search_groups.group(2),<br /> }<br /> return client_data<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def sysTran_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://www.systran.net/translate/<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param professional_field: str, default None.<br /> :return: str or dict<br /> """<br /><br /> use_domain = kwargs.get('professional_field', 'Generic')<br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> self.client_data = self.get_client_data(self.get_client_url, self.session, self.host_headers, timeout,<br /> proxies)<br /> payload = urllib.parse.urlencode(self.client_data)<br /> self.token_data = self.session.post(self.get_token_url, data=payload, headers=self.api_ajax_headers,<br /> timeout=timeout, proxies=proxies).json()<br /><br /> header_params = {<br /> 'authorization': f'{self.token_data["token_type"]} {self.token_data["access_token"]}',<br /> 'x-user-agent': 'File Translate Box Portable',<br /> }<br /> self.api_json_headers.update(header_params)<br /><br /> d_lang_map = self.session.get(self.get_lang_url, headers=self.api_json_headers, timeout=timeout,<br /> proxies=proxies).json()<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(d_lang_map, **debug_lang_kwargs)<br /> self.professional_field = self.get_professional_field_list(d_lang_map)<br /> self.langpair_domain = self.get_langpair_domain(d_lang_map)<br /><br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh)<br /> if from_language == 'auto':<br /> from_language = self.warning_auto_lang('sysTran', self.default_from_language, if_print_warning)<br /><br /> payload = {<br /> 'target': to_language,<br /> 'source': from_language if from_language != 'auto' else None,<br /> 'inputs': [paragraph for paragraph in query_text.split('\n') if paragraph.strip()],<br /> 'format': 'text/plain',<br /> 'autodetectionMode': 'single',<br /> 'withInfo': 'true',<br /> 'withAnnotations': 'true',<br /> 'profileId': None,<br /> 'domain': None,<br /> 'owner': None,<br /> 'size': None,<br /> }<br /> if use_domain and from_language != 'auto':<br /> domain_payload = self.langpair_domain.get(f'{from_language}__{to_language}__{use_domain}')<br /> if not domain_payload:<br /> raise TranslatorError<br /> else:<br /> payload.update(domain_payload)<br /><br /> r = self.session.post(self.api_url, json=payload, headers=self.api_json_headers, timeout=timeout,<br /> proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else '\n'.join(' '.join(it['alt_transes'][0]['target']['text'] for it in<br /> item['output']['documents'][0]['trans_units'][0][<br /> 'sentences']) for item in data['outputs'])<br /><br /><br />class TranslateMe(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://translateme.network/'<br /> self.api_url = 'https://translateme.network/wp-admin/admin-ajax.php'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False, if_referer_for_host=True)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_ajax_for_api=True)<br /> self.session = None<br /> self.language_map = None<br /> self.query_count = 0<br /> self.output_zh = 'Chinese'<br /> self.output_en = 'English'<br /> self.input_limit = int(1e2)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, host_html: str, **kwargs: LangMapKwargsType) -> dict:<br /> lang_list = re.compile('data-lang="(.*?)"').findall(host_html)<br /> if not lang_list:<br /> raise TranslatorError<br /><br /> lang_list = sorted(list(set(lang_list)))<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> # @Tse.uncertified<br /> # @Tse.time_stat<br /> # @Tse.check_query<br /> def _translateMe_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://translateme.network/<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(host_html, **debug_lang_kwargs)<br /><br /> if from_language == 'auto':<br /> from_language = self.warning_auto_lang('translateMe', self.default_from_language, if_print_warning)<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh,<br /> output_en_translator='translateMe', output_en=self.output_en)<br /> if self.output_en not in (from_language, to_language):<br /> raise TranslatorError('Must use English as an intermediate translation.')<br /><br /> data_list = []<br /> paragraphs = [paragraph for paragraph in query_text.split('\n') if paragraph.strip()]<br /> for paragraph in paragraphs:<br /> payload = {<br /> 'text': paragraph,<br /> 'lang_from': from_language,<br /> 'lang_to': to_language,<br /> 'action': 'tm_my_action',<br /> 'type': 'convert'<br /> }<br /> payload = urllib.parse.urlencode(payload)<br /> r = self.session.post(self.api_url, data=payload, headers=self.api_headers, timeout=timeout,<br /> proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> data_list.append(data)<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return {'data': data_list} if is_detail_result else '\n'.join([item['to'] for item in data_list])<br /><br /> @Tse.uncertified<br /> @Tse.time_stat<br /> @Tse.check_query<br /> def translateMe_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://translateme.network/<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(host_html, **debug_lang_kwargs)<br /><br /> if from_language == 'auto':<br /> from_language = self.warning_auto_lang('translateMe', self.default_from_language, if_print_warning)<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> output_zh=self.output_zh,<br /> output_en_translator='translateMe', output_en=self.output_en)<br /><br /> if self.output_en in (from_language, to_language):<br /> return self._translateMe_api(query_text, from_language, to_language, **kwargs)<br /><br /> tmp_kwargs = kwargs.copy()<br /> tmp_kwargs.update({'is_detail_result': False, 'if_show_time_stat': False})<br /> next_query_text = self._translateMe_api(query_text, from_language, self.output_en, **tmp_kwargs)<br /> return self._translateMe_api(next_query_text, self.output_en, to_language, **kwargs)<br /><br /><br />class Elia(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.host_url = 'https://elia.eus/translator'<br /> self.api_url = 'https://elia.eus/ajax/translate_string'<br /> self.detect_lang_url = 'https://elia.eus/ajax/language_detection'<br /> self.host_headers = self.get_headers(self.host_url, if_api=False, if_referer_for_host=True)<br /> self.api_headers = self.get_headers(self.host_url, if_api=True, if_ajax_for_api=True)<br /> self.session = None<br /> self.language_map = None<br /> self.professional_field = None<br /> self.langpair_domain = None<br /> self.token = None<br /> self.query_count = 0<br /> self.output_zh = None # unsupported<br /> self.input_limit = int(1e2)<br /> self.default_from_language = 'fr'<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, dd: dict, **kwargs: LangMapKwargsType) -> dict:<br /> return {ii['source_language']['code']: [jj['target_language']['code'] for jj in dd['language_pairs'] if<br /> jj['source_language']['code'] == ii['source_language']['code']] for ii<br /> in dd['language_pairs']}<br /><br /> def get_professional_field_list(self, dd: dict) -> set:<br /> return {it['translation_model']['code'] for it in dd['language_pairs']}<br /><br /> def get_langpair_domain(self, dd: dict) -> dict:<br /> data = {<br /> f'{item["source_language"]["code"]}__{item["target_language"]["code"]}__{item["translation_model"]["code"]}': {<br /> 'translation_engine': item["engine"]["pk"],<br /> } for item in dd['language_pairs']<br /> }<br /> return data<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def elia_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://elia.eus/translator<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param professional_field: str, default 'general'. Choose from ('general', 'admin').<br /> :return: str or dict<br /> """<br /><br /> use_domain = kwargs.get('professional_field', 'general')<br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> host_html = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout,<br /> proxies=proxies).text<br /> self.token = re.compile('"csrfmiddlewaretoken": "(.*?)"').search(host_html).group(1)<br /> d_lang_str = re.compile('var languagePairs = JSON.parse\\((.*?)\\);').search(host_html).group()<br /> d_lang_map = json.loads(d_lang_str[43:-4].replace('&quot;', '"'))<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(d_lang_map, **debug_lang_kwargs)<br /> self.professional_field = self.get_professional_field_list(d_lang_map)<br /> self.langpair_domain = self.get_langpair_domain(d_lang_map)<br /><br /> if from_language == 'auto':<br /> payload = {<br /> 'text': query_text,<br /> 'csrfmiddlewaretoken': self.token,<br /> }<br /> payload = urllib.parse.urlencode(payload)<br /> r = self.session.post(self.detect_lang_url, data=payload, headers=self.api_headers, timeout=timeout,<br /> proxies=proxies)<br /> from_language = r.json()['lang_id']<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map)<br /><br /> payload = {<br /> 'input_text': query_text,<br /> 'source_language': from_language,<br /> 'target_language': to_language,<br /> 'translation_model': use_domain,<br /> 'translation_engine': 1,<br /> 'csrfmiddlewaretoken': self.token,<br /> }<br /><br /> domain_payload = self.langpair_domain.get(f'{from_language}__{to_language}__{use_domain}')<br /> if not domain_payload:<br /> raise TranslatorError<br /> else:<br /> payload.update(domain_payload)<br /><br /> payload = urllib.parse.urlencode(payload)<br /> r = self.session.post(self.api_url, data=payload, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['translated_text'].replace('</div>', '\n').replace('<div>',<br /> '').replace(<br /> '<span>', '').replace('</span>', '')<br /><br /><br />class LanguageWire(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.home_url = 'https://jwt.languagewire.com'<br /> self.host_url = 'https://www.languagewire.com/en/technology/languagewire-translate'<br /> self.api_url = 'https://lwt.languagewire.com/f/api/v1/translations/text'<br /> self.lang_url = 'https://lwt.languagewire.com/f/api/v1/language-pairs?includeVariants=true'<br /> self.cookie_url = 'https://lwt.languagewire.com/f/api/v1/auth/cookie'<br /> self.lwt_js_url = 'https://lwt.languagewire.com/en/main.6f20295b104bc52a.js'<br /> self.host_headers = self.get_headers(self.home_url, if_api=False, if_referer_for_host=True)<br /> self.api_headers = self.get_headers(self.home_url, if_api=True, if_json_for_api=True)<br /> self.session = None<br /> self.language_map = None<br /> self.lwt_data = None<br /> self.query_count = 0<br /> self.output_zh = None # unsupported<br /> self.input_limit = int(5e3)<br /> self.default_from_language = 'fr'<br /> self.default_en_to_language = 'en-US'<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_url: str, ss: SessionType, headers: dict, timeout: Optional[float],<br /> proxies: Optional[dict], **kwargs: LangMapKwargsType) -> dict:<br /> d_lang_map = ss.get(lang_url, headers=headers, timeout=timeout, proxies=proxies).json()<br /> return {ii['sourceLanguage']['mmtCode']: [jj['targetLanguage']['mmtCode'] for jj in d_lang_map if<br /> jj['sourceLanguage']['mmtCode'] == ii['sourceLanguage']['mmtCode']]<br /> for ii in d_lang_map}<br /><br /> # def get_lwt_data(self, lwt_js_url: str, ss: SessionType, headers: dict, timeout: float, proxies: dict) -> dict:<br /> # js_html = ss.get(lwt_js_url, headers=headers, timeout=timeout, proxies=proxies).text<br /> # lwt_data = {<br /> # 'x-lwt-application-id': re.compile('"X-LWT-Application-ID":"(.*?)"').search(js_html).group(1),<br /> # 'x-lwt-build-id': re.compile('"X-LWT-Build-ID":"(.*?)"').search(js_html).group(1),<br /> # }<br /> # return lwt_data<br /><br /> def get_lwt_data(self) -> dict:<br /> lwt_data = {<br /> 'x-lwt-application-id': 'LWT_WEB',<br /> 'x-lwt-build-id': '346775',<br /> }<br /> return lwt_data<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def languageWire_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://www.languagewire.com/en/technology/languagewire-translate<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> self.lwt_data = self.get_lwt_data()<br /> self.api_headers.update(self.lwt_data)<br /><br /> _ = self.session.post(self.cookie_url, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.lang_url, self.session, self.api_headers, timeout, proxies,<br /> **debug_lang_kwargs)<br /><br /> if from_language == 'auto':<br /> from_language = self.warning_auto_lang('languageWire', self.default_from_language, if_print_warning)<br /> to_language = self.default_en_to_language if to_language == 'en' else to_language<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map,<br /> if_check_lang_reverse=False)<br /><br /> payload = {<br /> 'sourceText': query_text,<br /> 'sourceLanguage': from_language,<br /> 'targetLanguage': to_language,<br /> }<br /> r = self.session.post(self.api_url, json=payload, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['translation']<br /><br /><br />class Judic(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.home_url = 'https://judic.io'<br /> self.host_url = 'https://judic.io/en/translate'<br /> self.api_url = 'https://judic.io/translate/text'<br /> self.host_headers = self.get_headers(self.home_url, if_api=False, if_referer_for_host=True)<br /> self.api_headers = self.get_headers(self.home_url, if_api=True, if_json_for_api=True)<br /> self.session = None<br /> self.lang_list = ['en', 'de', 'fr', 'nl']<br /> self.language_map = None<br /> self.query_count = 0<br /> self.output_zh = None # unsupported<br /> self.input_limit = int(1e3)<br /> self.default_from_language = 'nl'<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_list: List[str], **kwargs: LangMapKwargsType) -> dict:<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> @Tse.time_stat<br /> @Tse.check_query<br /> def judic_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://judic.io/en/translate<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.lang_list, **debug_lang_kwargs)<br /><br /> if from_language == 'auto':<br /> from_language = self.warning_auto_lang('judic', self.default_from_language, if_print_warning)<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map)<br /><br /> payload = {<br /> 'sourceText': query_text,<br /> 'inputLang': from_language,<br /> 'outputLang': to_language<br /> }<br /> r = self.session.post(self.api_url, json=payload, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else data['translation']<br /><br /><br />class Yeekit(Tse):<br /> def __init__(self):<br /> super().__init__()<br /> self.begin_time = time.time()<br /> self.home_url = 'https://www.yeekit.com'<br /> self.host_url = 'https://www.yeekit.com/site/translate'<br /> self.api_url = 'https://www.yeekit.com/site/dotranslate'<br /> self.lang_url = 'https://www.yeekit.com/js/translate.js'<br /> self.host_headers = self.get_headers(self.home_url, if_api=False, if_referer_for_host=True)<br /> self.api_headers = self.get_headers(self.home_url, if_api=True, if_ajax_for_api=True)<br /> self.session = None<br /> self.lang_list = ['zh', 'en', 'ar', 'de', 'ru', 'fr', 'cz', 'pt', 'jp', 'es']<br /> self.language_map = None<br /> self.query_count = 0<br /> self.output_zh = 'zh'<br /> self.input_limit = int(1e3)<br /> self.default_from_language = self.output_zh<br /><br /> @Tse.debug_language_map<br /> def get_language_map(self, lang_list: List[str], **kwargs: LangMapKwargsType) -> dict:<br /> return {}.fromkeys(lang_list, lang_list)<br /><br /> @Tse.uncertified # not code, but server.<br /> @Tse.time_stat<br /> @Tse.check_query<br /> def yeekit_api(self, query_text: str, from_language: str = 'auto', to_language: str = 'en',<br /> **kwargs: ApiKwargsType) -> Union[str, dict]:<br /> """<br /> https://www.yeekit.com/site/translate<br /> :param query_text: str, must.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param **kwargs:<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param is_detail_result: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :return: str or dict<br /> """<br /><br /> timeout = kwargs.get('timeout', None)<br /> proxies = kwargs.get('proxies', None)<br /> sleep_seconds = kwargs.get('sleep_seconds', 0)<br /> if_print_warning = kwargs.get('if_print_warning', True)<br /> is_detail_result = kwargs.get('is_detail_result', False)<br /> update_session_after_freq = kwargs.get('update_session_after_freq', self.default_session_freq)<br /> update_session_after_seconds = kwargs.get('update_session_after_seconds', self.default_session_seconds)<br /> self.check_input_limit(query_text, self.input_limit)<br /><br /> not_update_cond_freq = 1 if self.query_count % update_session_after_freq != 0 else 0<br /> not_update_cond_time = 1 if time.time() - self.begin_time < update_session_after_seconds else 0<br /> if not (self.session and self.language_map and not_update_cond_freq and not_update_cond_time):<br /> self.begin_time = time.time()<br /> self.session = requests.Session()<br /> _ = self.session.get(self.host_url, headers=self.host_headers, timeout=timeout, proxies=proxies)<br /> debug_lang_kwargs = self.debug_lang_kwargs(from_language, to_language, self.default_from_language,<br /> if_print_warning)<br /> self.language_map = self.get_language_map(self.lang_list, **debug_lang_kwargs)<br /><br /> if from_language == 'auto':<br /> from_language = self.warning_auto_lang('yeekit', self.default_from_language, if_print_warning)<br /> from_language, to_language = self.check_language(from_language, to_language, self.language_map)<br /><br /> payload = {<br /> 'content[]': query_text,<br /> 'sourceLang': f'n{from_language}',<br /> 'targetLang': f'n{to_language}',<br /> }<br /> payload = urllib.parse.urlencode(payload)<br /> r = self.session.post(self.api_url, data=payload, headers=self.api_headers, timeout=timeout, proxies=proxies)<br /> r.raise_for_status()<br /> data = r.json()<br /> time.sleep(sleep_seconds)<br /> self.query_count += 1<br /> return data if is_detail_result else '\n'.join(<br /> ' '.join(p) for p in json.loads(data[0])['translation'][0]['translated'][0]['translation list'])<br /><br /><br />class TranslatorsServer:<br /> def __init__(self):<br /> self.cpu_cnt = os.cpu_count()<br /> self.server_region = 'CN'<br /> self._alibaba = AlibabaV2()<br /> self.alibaba = self._alibaba.alibaba_api<br /> self._apertium = Apertium()<br /> self.apertium = self._apertium.apertium_api<br /> self._argos = Argos()<br /> self.argos = self._argos.argos_api<br /> self._baidu = BaiduV1() # V2<br /> self.baidu = self._baidu.baidu_api<br /> self._bing = Bing(server_region=self.server_region)<br /> self.bing = self._bing.bing_api<br /> self._caiyun = Caiyun()<br /> self.caiyun = self._caiyun.caiyun_api<br /> self._cloudYi = CloudYi()<br /> self.cloudYi = self._cloudYi.cloudYi_api<br /> self._deepl = Deepl()<br /> self.deepl = self._deepl.deepl_api<br /> self._elia = Elia()<br /> self.elia = self._elia.elia_api<br /> self._google = GoogleV2(server_region=self.server_region)<br /> self.google = self._google.google_api<br /> self._iciba = Iciba()<br /> self.iciba = self._iciba.iciba_api<br /> self._iflytek = IflytekV2()<br /> self.iflytek = self._iflytek.iflytek_api<br /> self._iflyrec = Iflyrec()<br /> self.iflyrec = self._iflyrec.iflyrec_api<br /> self._itranslate = Itranslate()<br /> self.itranslate = self._itranslate.itranslate_api<br /> self._judic = Judic()<br /> self.judic = self._judic.judic_api<br /> self._languageWire = LanguageWire()<br /> self.languageWire = self._languageWire.languageWire_api<br /> self._lingvanex = Lingvanex()<br /> self.lingvanex = self._lingvanex.lingvanex_api<br /> self._mglip = Mglip()<br /> self.mglip = self._mglip.mglip_api<br /> self._mirai = Mirai()<br /> self.mirai = self._mirai.mirai_api<br /> self._modernMt = ModernMt()<br /> self.modernMt = self._modernMt.modernMt_api<br /> self._myMemory = MyMemory()<br /> self.myMemory = self._myMemory.myMemory_api<br /> self._papago = Papago()<br /> self.papago = self._papago.papago_api<br /> self._qqFanyi = QQFanyi()<br /> self.qqFanyi = self._qqFanyi.qqFanyi_api<br /> self._qqTranSmart = QQTranSmart()<br /> self.qqTranSmart = self._qqTranSmart.qqTranSmart_api<br /> self._reverso = Reverso()<br /> self.reverso = self._reverso.reverso_api<br /> self._sogou = Sogou()<br /> self.sogou = self._sogou.sogou_api<br /> self._sysTran = SysTran()<br /> self.sysTran = self._sysTran.sysTran_api<br /> self._tilde = Tilde()<br /> self.tilde = self._tilde.tilde_api<br /> self._translateCom = TranslateCom()<br /> self.translateCom = self._translateCom.translateCom_api<br /> self._translateMe = TranslateMe()<br /> self.translateMe = self._translateMe.translateMe_api<br /> self._utibet = Utibet()<br /> self.utibet = self._utibet.utibet_api<br /> self._volcEngine = VolcEngine()<br /> self.volcEngine = self._volcEngine.volcEngine_api<br /> self._yandex = Yandex()<br /> self.yandex = self._yandex.yandex_api<br /> self._yeekit = Yeekit()<br /> self.yeekit = self._yeekit.yeekit_api<br /> self._youdao = YoudaoV3()<br /> self.youdao = self._youdao.youdao_api<br /> self._translators_dict = {<br /> 'alibaba': self._alibaba, 'apertium': self._apertium, 'argos': self._argos, 'baidu': self._baidu,<br /> 'bing': self._bing,<br /> 'caiyun': self._caiyun, 'cloudYi': self._cloudYi, 'deepl': self._deepl, 'elia': self._elia,<br /> 'google': self._google,<br /> 'iciba': self._iciba, 'iflytek': self._iflytek, 'iflyrec': self._iflyrec, 'itranslate': self._itranslate,<br /> 'judic': self._judic,<br /> 'languageWire': self._languageWire, 'lingvanex': self._lingvanex,<br /> 'mglip': self._mglip, 'mirai': self._mirai,<br /> 'modernMt': self._modernMt, 'myMemory': self._myMemory, 'papago': self._papago, 'qqFanyi': self._qqFanyi,<br /> 'qqTranSmart': self._qqTranSmart,<br /> 'reverso': self._reverso, 'sogou': self._sogou, 'sysTran': self._sysTran, 'tilde': self._tilde,<br /> 'translateCom': self._translateCom,<br /> 'translateMe': self._translateMe, 'utibet': self._utibet, 'volcEngine': self._volcEngine,<br /> 'yandex': self._yandex, 'yeekit': self._yeekit,<br /> 'youdao': self._youdao,<br /> }<br /> self.translators_dict = {<br /> 'alibaba': self.alibaba, 'apertium': self.apertium, 'argos': self.argos, 'baidu': self.baidu,<br /> 'bing': self.bing,<br /> 'caiyun': self.caiyun, 'cloudYi': self.cloudYi, 'deepl': self.deepl, 'elia': self.elia,<br /> 'google': self.google,<br /> 'iciba': self.iciba, 'iflytek': self.iflytek, 'iflyrec': self.iflyrec, 'itranslate': self.itranslate,<br /> 'judic': self.judic,<br /> 'languageWire': self.languageWire, 'lingvanex': self.lingvanex,<br /> 'mglip': self.mglip, 'mirai': self.mirai,<br /> 'modernMt': self.modernMt, 'myMemory': self.myMemory, 'papago': self.papago, 'qqFanyi': self.qqFanyi,<br /> 'qqTranSmart': self.qqTranSmart,<br /> 'reverso': self.reverso, 'sogou': self.sogou, 'sysTran': self.sysTran, 'tilde': self.tilde,<br /> 'translateCom': self.translateCom,<br /> 'translateMe': self.translateMe, 'utibet': self.utibet, 'volcEngine': self.volcEngine,<br /> 'yandex': self.yandex, 'yeekit': self.yeekit,<br /> 'youdao': self.youdao,<br /> }<br /> self.translators_pool = list(self.translators_dict.keys())<br /> self.not_en_langs = {'utibet': 'ti', 'mglip': 'mon'}<br /> self.not_zh_langs = {'languageWire': 'fr', 'tilde': 'fr', 'elia': 'fr', 'apertium': 'spa'}<br /> self.pre_acceleration_label = 0<br /> self.example_query_text = '你好。\n欢迎你!'<br /> self.success_translators_pool = []<br /> self.failure_translators_pool = []<br /><br /> def translate_text(self,<br /> query_text: str,<br /> translator: str = 'bing',<br /> from_language: str = 'auto',<br /> to_language: str = 'en',<br /> if_use_preacceleration: bool = False,<br /> **kwargs: ApiKwargsType,<br /> ) -> Union[str, dict]:<br /> """<br /> :param query_text: str, must.<br /> :param translator: str, default 'bing'.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param if_use_preacceleration: bool, default False.<br /> :param **kwargs:<br /> :param is_detail_result: bool, default False.<br /> :param professional_field: str, support alibaba(), baidu(), caiyun(), cloudYi(), elia(), sysTran(), youdao(), volcEngine() only.<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_use_cn_host: bool, default False. Support google(), bing() only.<br /> :param reset_host_url: str, default None. Support google(), argos(), yandex() only.<br /> :param if_check_reset_host_url: bool, default True. Support google(), yandex() only.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param lingvanex_model: str, default 'B2C', choose from ("B2C", "B2B").<br /> :param myMemory_mode: str, default "web", choose from ("web", "api").<br /> :return: str or dict<br /> """<br /><br /> if translator not in self.translators_pool:<br /> raise TranslatorError<br /><br /> if not self.pre_acceleration_label and if_use_preacceleration:<br /> _ = self.preaccelerate()<br /><br /> return self.translators_dict[translator](query_text=query_text, from_language=from_language,<br /> to_language=to_language, **kwargs)<br /><br /> def translate_html(self,<br /> html_text: str,<br /> translator: str = 'bing',<br /> from_language: str = 'auto',<br /> to_language: str = 'en',<br /> n_jobs: int = -1,<br /> if_use_preacceleration: bool = False,<br /> **kwargs: ApiKwargsType,<br /> ) -> str:<br /> """<br /> Translate the displayed content of html without changing the html structure.<br /> :param html_text: str, must.<br /> :param translator: str, default 'bing'.<br /> :param from_language: str, default 'auto'.<br /> :param to_language: str, default 'en'.<br /> :param n_jobs: int, default -1, means os.cpu_cnt().<br /> :param if_use_preacceleration: bool, default False.<br /> :param **kwargs:<br /> :param is_detail_result: bool, default False.<br /> :param professional_field: str, support alibaba(), baidu(), caiyun(), cloudYi(), elia(), sysTran(), youdao(), volcEngine() only.<br /> :param timeout: float, default None.<br /> :param proxies: dict, default None.<br /> :param sleep_seconds: float, default 0.<br /> :param update_session_after_freq: int, default 1000.<br /> :param update_session_after_seconds: float, default 1500.<br /> :param if_use_cn_host: bool, default False. Support google(), bing() only.<br /> :param reset_host_url: str, default None. Support google(), argos(), yandex() only.<br /> :param if_check_reset_host_url: bool, default True. Support google(), yandex() only.<br /> :param if_ignore_empty_query: bool, default False.<br /> :param if_ignore_limit_of_length: bool, default False.<br /> :param limit_of_length: int, default 20000.<br /> :param if_show_time_stat: bool, default False.<br /> :param show_time_stat_precision: int, default 2.<br /> :param if_print_warning: bool, default True.<br /> :param lingvanex_model: str, default 'B2C', choose from ("B2C", "B2B").<br /> :param myMemory_mode: str, default "web", choose from ("web", "api").<br /> :return: str<br /> """<br /><br /> if translator not in self.translators_pool or kwargs.get('is_detail_result', False) or n_jobs > self.cpu_cnt:<br /> raise TranslatorError<br /><br /> if not self.pre_acceleration_label and if_use_preacceleration:<br /> _ = self.preaccelerate()<br /><br /> def _translate_text(sentence: str) -> Tuple[str, str]:<br /> return sentence, self.translators_dict[translator](query_text=sentence, from_language=from_language,<br /> to_language=to_language, **kwargs)<br /><br /> pattern = re.compile(<br /> "(?:^|(?<=>))([\\s\\S]*?)(?:(?=<)|$)") # TODO: <code></code> <div class="codetext notranslate"><br /> sentence_list = list(set(pattern.findall(html_text)))<br /><br /> n_jobs = self.cpu_cnt if n_jobs <= 0 else n_jobs<br /> with pathos.multiprocessing.ProcessPool(n_jobs) as pool:<br /> result_list = pool.map(_translate_text, sentence_list)<br /><br /> result_dict = {text: ts_text for text, ts_text in result_list}<br /> _get_result_func = lambda k: result_dict.get(k.group(1), '')<br /> return pattern.sub(repl=_get_result_func, string=html_text)<br /><br /> def _test_translate(self, _ts: str, timeout: Optional[float] = None, if_show_time_stat: bool = False) -> str:<br /> from_language = self.not_zh_langs[_ts] if _ts in self.not_zh_langs else 'auto'<br /> to_language = self.not_en_langs[_ts] if _ts in self.not_en_langs else 'en'<br /> result = self.translators_dict[_ts](<br /> query_text=self.example_query_text,<br /> translator=_ts,<br /> from_language=from_language,<br /> to_language=to_language,<br /> if_print_warning=False,<br /> timeout=timeout,<br /> if_show_time_stat=if_show_time_stat<br /> )<br /> return result<br /><br /> def get_languages(self, translator: str = 'bing'):<br /> language_map = self._translators_dict[translator].language_map<br /> if language_map:<br /> return language_map<br /><br /> _ = self._test_translate(_ts=translator)<br /> return self._translators_dict[translator].language_map<br /><br /> def preaccelerate(self, timeout: Optional[float] = None, if_show_time_stat: bool = True, **kwargs: str) -> dict:<br /> if self.pre_acceleration_label > 0:<br /> raise TranslatorError('Preacceleration can only be performed once.')<br /><br /> self.example_query_text = kwargs.get('example_query_text', self.example_query_text)<br /><br /> sys.stderr.write('Preacceleration-Process will take a few minutes.\n')<br /> sys.stderr.write('Tips: The smaller `timeout` value, the fewer translators pass the test '<br /> 'and the less time it takes to preaccelerate. However, the slow speed of '<br /> 'preacceleration does not mean the slow speed of later translation.\n\n')<br /><br /> for i in tqdm.tqdm(range(len(self.translators_pool)), desc='Preacceleration Process', ncols=80):<br /> _ts = self.translators_pool[i]<br /> try:<br /> _ = self._test_translate(_ts, timeout, if_show_time_stat)<br /> self.success_translators_pool.append(_ts)<br /> except:<br /> self.failure_translators_pool.append(_ts)<br /><br /> self.pre_acceleration_label += 1<br /> return {'success': self.success_translators_pool, 'failure': self.failure_translators_pool}<br /><br /> def speedtest(self, **kwargs: List[str]) -> None:<br /> if self.pre_acceleration_label < 1:<br /> raise TranslatorError('Preacceleration first.')<br /><br /> test_translators_pool = kwargs.get('test_translators_pool', self.success_translators_pool)<br /><br /> sys.stderr.write('SpeedTest-Process will take a few seconds.\n\n')<br /> for i in tqdm.tqdm(range(len(test_translators_pool)), desc='SpeedTest Process', ncols=80):<br /> _ts = test_translators_pool[i]<br /> try:<br /> _ = self._test_translate(_ts, timeout=None, if_show_time_stat=True)<br /> except:<br /> pass<br /> return<br /><br /> def preaccelerate_and_speedtest(self, timeout: Optional[float] = None, **kwargs: str) -> dict:<br /> result = self.preaccelerate(timeout=timeout, **kwargs)<br /> sys.stderr.write('\n\n')<br /> self.speedtest()<br /> return result<br /><br /><br />tss = TranslatorsServer()<br /><br />_alibaba = tss._alibaba<br />alibaba = tss.alibaba<br />_apertium = tss._apertium<br />apertium = tss.apertium<br />_argos = tss._argos<br />argos = tss.argos<br />_baidu = tss._baidu<br />baidu = tss.baidu<br />_bing = tss._bing<br />bing = tss.bing<br />_caiyun = tss._caiyun<br />caiyun = tss.caiyun<br />_cloudYi = tss._cloudYi<br />cloudYi = tss.cloudYi<br />_deepl = tss._deepl<br />deepl = tss.deepl<br />_elia = tss._elia<br />elia = tss.elia<br />_google = tss._google<br />google = tss.google<br />_iciba = tss._iciba<br />iciba = tss.iciba<br />_iflytek = tss._iflytek<br />iflytek = tss.iflytek<br />_iflyrec = tss._iflyrec<br />iflyrec = tss.iflyrec<br />_itranslate = tss._itranslate<br />itranslate = tss.itranslate<br />_judic = tss._judic<br />judic = tss.judic<br />_languageWire = tss._languageWire<br />languageWire = tss.languageWire<br />_lingvanex = tss._lingvanex<br />lingvanex = tss.lingvanex<br />_mglip = tss._mglip<br />mglip = tss.mglip<br />_mirai = tss._mirai<br />mirai = tss.mirai<br />_modernMt = tss._modernMt<br />modernMt = tss.modernMt<br />_myMemory = tss._myMemory<br />myMemory = tss.myMemory<br />_papago = tss._papago<br />papago = tss.papago<br />_qqFanyi = tss._qqFanyi<br />qqFanyi = tss.qqFanyi<br />_qqTranSmart = tss._qqTranSmart<br />qqTranSmart = tss.qqTranSmart<br />_reverso = tss._reverso<br />reverso = tss.reverso<br />_sogou = tss._sogou<br />sogou = tss.sogou<br />_sysTran = tss._sysTran<br />sysTran = tss.sysTran<br />_tilde = tss._tilde<br />tilde = tss.tilde<br />_translateCom = tss._translateCom<br />translateCom = tss.translateCom<br />_translateMe = tss._translateMe<br />translateMe = tss.translateMe<br />_utibet = tss._utibet<br />utibet = tss.utibet<br />_volcEngine = tss._volcEngine<br />volcEngine = tss.volcEngine<br />_yandex = tss._yandex<br />yandex = tss.yandex<br />_yeekit = tss._yeekit<br />yeekit = tss.yeekit<br />_youdao = tss._youdao<br />youdao = tss.youdao<br /><br />translate_text = tss.translate_text<br />translate_html = tss.translate_html<br />translators_pool = tss.translators_pool<br />get_languages = tss.get_languages<br /><br />preaccelerate = tss.preaccelerate<br />speedtest = tss.speedtest<br />preaccelerate_and_speedtest = tss.preaccelerate_and_speedtest<br /># sys.stderr.write(f'Support translators {translators_pool} only.\n')<br /><br />if __name__ == '__main__':<br /> pass</p>Tiberiu Cristian Leonhttp://www.blogger.com/profile/16802277287976622797noreply@blogger.com