master
Oystein Kristoffer Tveit 2020-06-26 18:14:00 +02:00
parent e119a81960
commit 93f1a49c89
8 changed files with 262 additions and 301 deletions

View File

@ -1,8 +1,9 @@
/// This library provides search functions for searching/scraping Jisho.org.
///
///
/// It provides a built-in http client and performs async requests to the server
/// for different types of requests.
library unofficial_jisho_api;
import 'dart:convert';
import 'package:http/http.dart' as http;
@ -13,28 +14,34 @@ import './src/phraseScrape.dart';
import './src/phraseSearch.dart';
/// Query the official Jisho API for a word or phrase
///
///
/// See https://jisho.org/forum/54fefc1f6e73340b1f160000-is-there-any-kind-of-search-api
/// for discussion about the official API.
Future<JishoAPIResult> searchForPhrase(String phrase) async {
final uri = uriForPhraseSearch(phrase);
return await http.get(uri).then((response) => JishoAPIResult.fromJson(jsonDecode(response.body)));
return await http
.get(uri)
.then((response) => JishoAPIResult.fromJson(jsonDecode(response.body)));
}
/// Scrape Jisho.org for information about a kanji character.
Future<KanjiResult> searchForKanji(String kanji) async {
final uri = uriForKanjiSearch(kanji);
return http.get(uri).then((response) => parseKanjiPageData(response.body, kanji));
return http
.get(uri)
.then((response) => parseKanjiPageData(response.body, kanji));
}
/// Scrape Jisho.org for examples.
Future<ExampleResults> searchForExamples(String phrase) async {
final uri = uriForExampleSearch(phrase);
return http.get(uri).then((response) => parseExamplePageData(response.body, phrase));
return http
.get(uri)
.then((response) => parseExamplePageData(response.body, phrase));
}
/// Scrape the word page for a word/phrase.
///
///
/// This allows you to get some information that isn't provided by the official API, such as
/// part-of-speech and JLPT level. However, the official API should be preferred
/// if it has the information you need. This function scrapes https://jisho.org/word/XXX.
@ -50,4 +57,4 @@ Future<PhrasePageScrapeResult> scrapeForPhrase(String phrase) async {
);
}
return parsePhrasePageData(response.body, phrase);
}
}

View File

@ -1,11 +1,12 @@
/// This library provides parsing functions for html pages from Jisho.org,
/// and the associated URI-producing functions.
///
///
/// This might be useful for using a CORS proxy, or if you have your own system/library
/// for providing HTML.
library unofficial_jisho_parser;
export './src/exampleSearch.dart' show uriForExampleSearch, parseExamplePageData;
export './src/exampleSearch.dart'
show uriForExampleSearch, parseExamplePageData;
export './src/kanjiSearch.dart' show uriForKanjiSearch, parseKanjiPageData;
export './src/phraseScrape.dart' show uriForPhraseScrape, parsePhrasePageData;
export './src/phraseSearch.dart';
export './src/phraseSearch.dart';

View File

@ -1,3 +1,4 @@
const String JISHO_API = 'https://jisho.org/api/v1/search/words';
const String SCRAPE_BASE_URI = 'https://jisho.org/search/';
const String STROKE_ORDER_DIAGRAM_BASE_URI = 'https://classic.jisho.org/static/images/stroke_diagrams/';
const String STROKE_ORDER_DIAGRAM_BASE_URI =
'https://classic.jisho.org/static/images/stroke_diagrams/';

View File

@ -19,21 +19,22 @@ List<Element> _getChildrenAndSymbols(Element ul) {
List<Element> result = [];
for (var element in ulChildren) {
if (element.text != ulText.substring(offsetPointer, offsetPointer + element.text.length)){
if (element.text !=
ulText.substring(offsetPointer, offsetPointer + element.text.length)) {
var symbols = '';
while (element.text.substring(0,1) != ulCharArray[offsetPointer]) {
while (element.text.substring(0, 1) != ulCharArray[offsetPointer]) {
symbols += ulCharArray[offsetPointer];
offsetPointer++;
}
final symbolElement = Element.html('<span>$symbols</span>');
final symbolElement = Element.html('<span>$symbols</span>');
result.add(symbolElement);
}
offsetPointer += element.text.length;
result.add(element);
offsetPointer += element.text.length;
result.add(element);
}
if (offsetPointer + 1 != ulText.length){
final symbols = ulText.substring(offsetPointer, ulText.length-1);
final symbolElement = Element.html('<span>$symbols</span>');
if (offsetPointer + 1 != ulText.length) {
final symbols = ulText.substring(offsetPointer, ulText.length - 1);
final symbolElement = Element.html('<span>$symbols</span>');
result.add(symbolElement);
}
return result;
@ -122,4 +123,4 @@ ExampleResults parseExamplePageData(String pageHtml, String phrase) {
uri: uriForExampleSearch(phrase),
phrase: phrase,
);
}
}

View File

@ -9,7 +9,7 @@ const _onyomiLocatorSymbol = 'On';
const _kunyomiLocatorSymbol = 'Kun';
String _removeNewlines(String str) {
return str.replaceAll(RegExp(r'(?:\r|\n)') , '').trim();
return str.replaceAll(RegExp(r'(?:\r|\n)'), '').trim();
}
/// Provides the URI for a kanji search
@ -22,7 +22,8 @@ String _getUriForStrokeOrderDiagram(String kanji) {
}
bool _containsKanjiGlyph(String pageHtml, String kanji) {
final kanjiGlyphToken = '<h1 class="character" data-area-name="print" lang="ja">$kanji</h1>';
final kanjiGlyphToken =
'<h1 class="character" data-area-name="print" lang="ja">$kanji</h1>';
return pageHtml.contains(kanjiGlyphToken);
}
@ -31,15 +32,20 @@ String _getStringBetweenIndicies(String data, int startIndex, int endIndex) {
return _removeNewlines(result).trim();
}
String _getStringBetweenStrings(String data, String startString, String endString) {
final regex = RegExp('${RegExp.escape(startString)}(.*?)${RegExp.escape(endString)}', dotAll: true);
String _getStringBetweenStrings(
String data, String startString, String endString) {
final regex = RegExp(
'${RegExp.escape(startString)}(.*?)${RegExp.escape(endString)}',
dotAll: true);
final match = regex.allMatches(data).toList();
return match.isNotEmpty ? match[0].group(1).toString() : null;
}
int _getIntBetweenStrings(String pageHtml, String startString, String endString) {
final stringBetweenStrings = _getStringBetweenStrings(pageHtml, startString, endString);
int _getIntBetweenStrings(
String pageHtml, String startString, String endString) {
final stringBetweenStrings =
_getStringBetweenStrings(pageHtml, startString, endString);
return int.parse(stringBetweenStrings);
}
@ -59,7 +65,8 @@ List<String> _parseAnchorsToArray(String str) {
}
List<String> _getYomi(String pageHtml, String yomiLocatorSymbol) {
final yomiSection = _getStringBetweenStrings(pageHtml, '<dt>$yomiLocatorSymbol:</dt>', '</dl>');
final yomiSection = _getStringBetweenStrings(
pageHtml, '<dt>$yomiLocatorSymbol:</dt>', '</dl>');
return _parseAnchorsToArray(yomiSection ?? '');
}
@ -73,13 +80,15 @@ List<String> _getOnyomi(String pageHtml) {
List<YomiExample> _getYomiExamples(String pageHtml, String yomiLocatorSymbol) {
final locatorString = '<h2>$yomiLocatorSymbol reading compounds</h2>';
final exampleSection = _getStringBetweenStrings(pageHtml, locatorString, '</ul>');
if (exampleSection==null) {
final exampleSection =
_getStringBetweenStrings(pageHtml, locatorString, '</ul>');
if (exampleSection == null) {
return null;
}
final regex = RegExp(r'<li>(.*?)<\/li>', dotAll: true);
final regexResults = _getAllGlobalGroupMatches(exampleSection, regex).map((s) => s.trim());
final regexResults =
_getAllGlobalGroupMatches(exampleSection, regex).map((s) => s.trim());
final examples = regexResults.map((regexResult) {
final examplesLines = regexResult.split('\n').map((s) => s.trim()).toList();
@ -111,17 +120,20 @@ Radical _getRadical(String pageHtml) {
radicalMeaningEndString,
).trim();
if (radicalMeaning!=null) {
final radicalMeaningStartIndex = pageHtml.indexOf(radicalMeaningStartString);
if (radicalMeaning != null) {
final radicalMeaningStartIndex =
pageHtml.indexOf(radicalMeaningStartString);
final radicalMeaningEndIndex = pageHtml.indexOf(
radicalMeaningEndString,
radicalMeaningStartIndex,
);
final radicalSymbolStartIndex = radicalMeaningEndIndex + radicalMeaningEndString.length;
final radicalSymbolStartIndex =
radicalMeaningEndIndex + radicalMeaningEndString.length;
const radicalSymbolEndString = '</span>';
final radicalSymbolEndIndex = pageHtml.indexOf(radicalSymbolEndString, radicalSymbolStartIndex);
final radicalSymbolEndIndex =
pageHtml.indexOf(radicalSymbolEndString, radicalSymbolStartIndex);
final radicalSymbolsString = _getStringBetweenIndicies(
pageHtml,
@ -131,23 +143,19 @@ Radical _getRadical(String pageHtml) {
if (radicalSymbolsString.length > 1) {
final radicalForms = radicalSymbolsString
.substring(1)
.replaceAll('(', '')
.replaceAll(')', '')
.trim()
.split(', ');
.substring(1)
.replaceAll('(', '')
.replaceAll(')', '')
.trim()
.split(', ');
return Radical(
symbol: radicalSymbolsString[0],
forms: radicalForms ?? [],
meaning: radicalMeaning
);
symbol: radicalSymbolsString[0],
forms: radicalForms ?? [],
meaning: radicalMeaning);
}
return Radical (
symbol: radicalSymbolsString,
meaning: radicalMeaning
);
return Radical(symbol: radicalSymbolsString, meaning: radicalMeaning);
}
return null;
@ -178,14 +186,19 @@ String _getSvgUri(String pageHtml) {
String _getGifUri(String kanji) {
final unicodeString = kanji.codeUnitAt(0).toRadixString(16);
final fileName = '$unicodeString.gif';
final animationUri = 'https://raw.githubusercontent.com/mistval/kanji_images/master/gifs/$fileName';
final animationUri =
'https://raw.githubusercontent.com/mistval/kanji_images/master/gifs/$fileName';
return animationUri;
}
int _getNewspaperFrequencyRank(String pageHtml) {
final frequencySection = _getStringBetweenStrings(pageHtml, '<div class="frequency">', '</div>');
return (frequencySection != null) ? int.parse(_getStringBetweenStrings(frequencySection, '<strong>', '</strong>')) : null;
final frequencySection =
_getStringBetweenStrings(pageHtml, '<div class="frequency">', '</div>');
return (frequencySection != null)
? int.parse(
_getStringBetweenStrings(frequencySection, '<strong>', '</strong>'))
: null;
}
/// Parses a jisho kanji search page to an object
@ -193,15 +206,21 @@ KanjiResult parseKanjiPageData(String pageHtml, String kanji) {
final result = KanjiResult();
result.query = kanji;
result.found = _containsKanjiGlyph(pageHtml, kanji);
if (result.found==false) {
if (result.found == false) {
return result;
}
result.taughtIn = _getStringBetweenStrings(pageHtml, 'taught in <strong>', '</strong>');
result.jlptLevel = _getStringBetweenStrings(pageHtml, 'JLPT level <strong>', '</strong>');
result.taughtIn =
_getStringBetweenStrings(pageHtml, 'taught in <strong>', '</strong>');
result.jlptLevel =
_getStringBetweenStrings(pageHtml, 'JLPT level <strong>', '</strong>');
result.newspaperFrequencyRank = _getNewspaperFrequencyRank(pageHtml);
result.strokeCount = _getIntBetweenStrings(pageHtml, '<strong>', '</strong> strokes');
result.meaning = _htmlUnescape.convert(_removeNewlines(_getStringBetweenStrings(pageHtml, '<div class="kanji-details__main-meanings">', '</div>')).trim());
result.strokeCount =
_getIntBetweenStrings(pageHtml, '<strong>', '</strong> strokes');
result.meaning = _htmlUnescape.convert(_removeNewlines(
_getStringBetweenStrings(
pageHtml, '<div class="kanji-details__main-meanings">', '</div>'))
.trim());
result.kunyomi = _getKunyomi(pageHtml) ?? [];
result.onyomi = _getOnyomi(pageHtml) ?? [];
result.onyomiExamples = _getOnyomiExamples(pageHtml) ?? [];
@ -213,4 +232,4 @@ KanjiResult parseKanjiPageData(String pageHtml, String kanji) {
result.strokeOrderGifUri = _getGifUri(kanji);
result.uri = uriForKanjiSearch(kanji);
return result;
}
}

View File

@ -7,19 +7,10 @@ class YomiExample {
String reading;
String meaning;
YomiExample({
this.example,
this.reading,
this.meaning
});
YomiExample({this.example, this.reading, this.meaning});
Map<String, String> toJson() =>
{
'example': example,
'reading': reading,
'meaning': meaning
};
{'example': example, 'reading': reading, 'meaning': meaning};
}
class Radical {
@ -27,19 +18,10 @@ class Radical {
List<String> forms;
String meaning;
Radical({
this.symbol,
this.forms,
this.meaning
});
Radical({this.symbol, this.forms, this.meaning});
Map<String, dynamic> toJson() =>
{
'symbol': symbol,
'forms': forms,
'meaning': meaning
};
{'symbol': symbol, 'forms': forms, 'meaning': meaning};
}
class KanjiResult {
@ -62,25 +44,24 @@ class KanjiResult {
String strokeOrderGifUri;
String uri;
KanjiResult({
this.query,
this.found,
this.taughtIn,
this.jlptLevel,
this.newspaperFrequencyRank,
this.strokeCount,
this.meaning,
this.kunyomi,
this.onyomi,
this.kunyomiExamples,
this.onyomiExamples,
this.radical,
this.parts,
this.strokeOrderDiagramUri,
this.strokeOrderSvgUri,
this.strokeOrderGifUri,
this.uri
});
KanjiResult(
{this.query,
this.found,
this.taughtIn,
this.jlptLevel,
this.newspaperFrequencyRank,
this.strokeCount,
this.meaning,
this.kunyomi,
this.onyomi,
this.kunyomiExamples,
this.onyomiExamples,
this.radical,
this.parts,
this.strokeOrderDiagramUri,
this.strokeOrderSvgUri,
this.strokeOrderGifUri,
this.uri});
Map<String, dynamic> toJson() {
return {
@ -113,16 +94,10 @@ class ExampleSentencePiece {
String lifted;
String unlifted;
ExampleSentencePiece({
this.lifted,
this.unlifted
});
ExampleSentencePiece({this.lifted, this.unlifted});
Map<String, dynamic> toJson() {
return {
'lifted': lifted,
'unlifted': unlifted
};
return {'lifted': lifted, 'unlifted': unlifted};
}
}
@ -132,20 +107,10 @@ class ExampleResultData {
String english;
List<ExampleSentencePiece> pieces;
ExampleResultData({
this.english,
this.kanji,
this.kana,
this.pieces
});
ExampleResultData({this.english, this.kanji, this.kana, this.pieces});
Map<String, dynamic> toJson() {
return {
'english': english,
'kanji': kanji,
'kana': kana,
'pieces': pieces
};
return {'english': english, 'kanji': kanji, 'kana': kana, 'pieces': pieces};
}
}
@ -156,13 +121,7 @@ class ExampleResults {
List<ExampleResultData> results;
String phrase;
ExampleResults({
this.query,
this.found,
this.results,
this.uri,
this.phrase
});
ExampleResults({this.query, this.found, this.results, this.uri, this.phrase});
Map<String, dynamic> toJson() {
return {
@ -184,17 +143,10 @@ class PhraseScrapeSentence {
String japanese;
List<ExampleSentencePiece> pieces;
PhraseScrapeSentence ({
this.english,
this.japanese,
this.pieces
});
PhraseScrapeSentence({this.english, this.japanese, this.pieces});
Map<String, dynamic> toJson() => {
'english': english,
'japanese': japanese,
'pieces': pieces
};
Map<String, dynamic> toJson() =>
{'english': english, 'japanese': japanese, 'pieces': pieces};
}
class PhraseScrapeMeaning {
@ -205,38 +157,31 @@ class PhraseScrapeMeaning {
String definitionAbstract;
List<String> tags;
PhraseScrapeMeaning({
this.seeAlsoTerms,
this.sentences,
this.definition,
this.supplemental,
this.definitionAbstract,
this.tags
});
PhraseScrapeMeaning(
{this.seeAlsoTerms,
this.sentences,
this.definition,
this.supplemental,
this.definitionAbstract,
this.tags});
Map<String, dynamic> toJson() => {
'seeAlsoTerms': seeAlsoTerms,
'sentences': sentences,
'definition': definition,
'supplemental': supplemental,
'definitionAbstract': definitionAbstract,
'tags': tags
};
'seeAlsoTerms': seeAlsoTerms,
'sentences': sentences,
'definition': definition,
'supplemental': supplemental,
'definitionAbstract': definitionAbstract,
'tags': tags
};
}
class KanjiKanaPair {
String kanji;
String kana;
KanjiKanaPair({
this.kanji,
this.kana
});
KanjiKanaPair({this.kanji, this.kana});
Map<String, String> toJson() => {
'kanji': kanji,
'kana': kana
};
Map<String, String> toJson() => {'kanji': kanji, 'kana': kana};
}
class PhrasePageScrapeResult {
@ -248,25 +193,24 @@ class PhrasePageScrapeResult {
List<KanjiKanaPair> otherForms;
List<String> notes;
PhrasePageScrapeResult({
this.found,
this.query,
this.uri,
this.tags,
this.meanings,
this.otherForms,
this.notes
});
PhrasePageScrapeResult(
{this.found,
this.query,
this.uri,
this.tags,
this.meanings,
this.otherForms,
this.notes});
Map<String, dynamic> toJson() => {
'found': found,
'query': query,
'uri': uri,
'tags': tags,
'meanings': meanings,
'otherForms': otherForms,
'notes': notes
};
'found': found,
'query': query,
'uri': uri,
'tags': tags,
'meanings': meanings,
'otherForms': otherForms,
'notes': notes
};
}
/* -------------------------------------------------------------------------- */
@ -279,17 +223,12 @@ class JishoJapaneseWord {
JishoJapaneseWord({this.word, this.reading});
factory JishoJapaneseWord.fromJson(Map<String, dynamic> json){
factory JishoJapaneseWord.fromJson(Map<String, dynamic> json) {
return JishoJapaneseWord(
word: json['word'] as String,
reading: json['reading'] as String
);
word: json['word'] as String, reading: json['reading'] as String);
}
Map<String, dynamic> toJson() => {
'word': word,
'reading': reading
};
Map<String, dynamic> toJson() => {'word': word, 'reading': reading};
}
class JishoSenseLink {
@ -298,17 +237,12 @@ class JishoSenseLink {
JishoSenseLink({this.text, this.url});
factory JishoSenseLink.fromJson(Map<String, dynamic> json){
factory JishoSenseLink.fromJson(Map<String, dynamic> json) {
return JishoSenseLink(
text: json['text'] as String,
url: json['url'] as String
);
text: json['text'] as String, url: json['url'] as String);
}
Map<String, dynamic> toJson() => {
'text': text,
'url': url
};
Map<String, dynamic> toJson() => {'text': text, 'url': url};
}
class JishoWordSense {
@ -322,43 +256,51 @@ class JishoWordSense {
List<String> info;
List<dynamic> restrictions;
JishoWordSense({
this.english_definitions,
this.parts_of_speech,
this.links,
this.tags,
this.see_also,
this.antonyms,
this.source,
this.info,
this.restrictions
});
JishoWordSense(
{this.english_definitions,
this.parts_of_speech,
this.links,
this.tags,
this.see_also,
this.antonyms,
this.source,
this.info,
this.restrictions});
factory JishoWordSense.fromJson(Map<String, dynamic> json){
factory JishoWordSense.fromJson(Map<String, dynamic> json) {
return JishoWordSense(
english_definitions: (json['english_definitions'] as List).map((result) => result as String).toList(),
parts_of_speech: (json['parts_of_speech'] as List).map((result) => result as String).toList(),
links: (json['links'] as List).map((result) => JishoSenseLink.fromJson(result)).toList(),
tags: (json['tags'] as List).map((result) => result as String).toList(),
see_also: (json['see_also'] as List).map((result) => result as String).toList(),
antonyms: (json['antonyms'] as List).map((result) => result as String).toList(),
source: json['source'] as List<dynamic>,
info: (json['info'] as List).map((result) => result as String).toList(),
restrictions: json['restrictions'] as List<dynamic>
);
english_definitions: (json['english_definitions'] as List)
.map((result) => result as String)
.toList(),
parts_of_speech: (json['parts_of_speech'] as List)
.map((result) => result as String)
.toList(),
links: (json['links'] as List)
.map((result) => JishoSenseLink.fromJson(result))
.toList(),
tags: (json['tags'] as List).map((result) => result as String).toList(),
see_also: (json['see_also'] as List)
.map((result) => result as String)
.toList(),
antonyms: (json['antonyms'] as List)
.map((result) => result as String)
.toList(),
source: json['source'] as List<dynamic>,
info: (json['info'] as List).map((result) => result as String).toList(),
restrictions: json['restrictions'] as List<dynamic>);
}
Map<String, dynamic> toJson() => {
'english_definitions': english_definitions,
'parts_of_speech': parts_of_speech,
'links': links,
'tags': tags,
'see_also': see_also,
'antonyms': antonyms,
'source': source,
'info': info,
'restrictions': restrictions
};
'english_definitions': english_definitions,
'parts_of_speech': parts_of_speech,
'links': links,
'tags': tags,
'see_also': see_also,
'antonyms': antonyms,
'source': source,
'info': info,
'restrictions': restrictions
};
}
class JishoAttribution {
@ -366,25 +308,19 @@ class JishoAttribution {
bool jmnedict;
String dbpedia;
JishoAttribution({
this.jmdict,
this.jmnedict,
this.dbpedia
});
JishoAttribution({this.jmdict, this.jmnedict, this.dbpedia});
factory JishoAttribution.fromJson(Map<String, dynamic> json){
factory JishoAttribution.fromJson(Map<String, dynamic> json) {
return JishoAttribution(
jmdict: (json['jmdict'].toString() == 'true'),
jmnedict: (json['jmnedict'].toString() == 'true'),
dbpedia: (json['dbpedia'].toString() != 'false') ? json['dbpedia'].toString() : null
);
jmdict: (json['jmdict'].toString() == 'true'),
jmnedict: (json['jmnedict'].toString() == 'true'),
dbpedia: (json['dbpedia'].toString() != 'false')
? json['dbpedia'].toString()
: null);
}
Map<String, dynamic> toJson() => {
'jmdict': jmdict,
'jmnedict': jmnedict,
'dbpedia': dbpedia
};
Map<String, dynamic> toJson() =>
{'jmdict': jmdict, 'jmnedict': jmnedict, 'dbpedia': dbpedia};
}
class JishoResult {
@ -396,37 +332,39 @@ class JishoResult {
List<JishoWordSense> senses;
JishoAttribution attribution;
JishoResult({
this.slug,
this.is_common,
this.tags,
this.jlpt,
this.japanese,
this.senses,
this.attribution
});
JishoResult(
{this.slug,
this.is_common,
this.tags,
this.jlpt,
this.japanese,
this.senses,
this.attribution});
factory JishoResult.fromJson(Map<String, dynamic> json){
factory JishoResult.fromJson(Map<String, dynamic> json) {
return JishoResult(
slug: json['slug'] as String,
is_common: json['is_common'] as bool,
tags: (json['tags'] as List).map((result) => result as String).toList(),
jlpt: (json['jlpt'] as List).map((result) => result as String).toList(),
japanese: (json['japanese'] as List).map((result) => JishoJapaneseWord.fromJson(result)).toList(),
senses: (json['senses'] as List).map((result) => JishoWordSense.fromJson(result)).toList(),
attribution: JishoAttribution.fromJson(json['attribution'])
);
slug: json['slug'] as String,
is_common: json['is_common'] as bool,
tags: (json['tags'] as List).map((result) => result as String).toList(),
jlpt: (json['jlpt'] as List).map((result) => result as String).toList(),
japanese: (json['japanese'] as List)
.map((result) => JishoJapaneseWord.fromJson(result))
.toList(),
senses: (json['senses'] as List)
.map((result) => JishoWordSense.fromJson(result))
.toList(),
attribution: JishoAttribution.fromJson(json['attribution']));
}
Map<String, dynamic> toJson() => {
'slug': slug,
'is_common': is_common,
'tags': tags,
'jlpt': jlpt,
'japanese': japanese,
'senses': senses,
'attribution': attribution
};
'slug': slug,
'is_common': is_common,
'tags': tags,
'jlpt': jlpt,
'japanese': japanese,
'senses': senses,
'attribution': attribution
};
}
class JishoResultMeta {
@ -434,15 +372,11 @@ class JishoResultMeta {
JishoResultMeta({this.status});
factory JishoResultMeta.fromJson(Map<String, dynamic> json){
return JishoResultMeta(
status: json['status'] as int
);
factory JishoResultMeta.fromJson(Map<String, dynamic> json) {
return JishoResultMeta(status: json['status'] as int);
}
Map<String, dynamic> toJson() => {
'status': status
};
Map<String, dynamic> toJson() => {'status': status};
}
class JishoAPIResult {
@ -451,15 +385,13 @@ class JishoAPIResult {
JishoAPIResult({this.meta, this.data});
factory JishoAPIResult.fromJson(Map<String, dynamic> json){
factory JishoAPIResult.fromJson(Map<String, dynamic> json) {
return JishoAPIResult(
meta: JishoResultMeta.fromJson(json['meta']),
data: (json['data'] as List).map((result) => JishoResult.fromJson(result)).toList()
);
meta: JishoResultMeta.fromJson(json['meta']),
data: (json['data'] as List)
.map((result) => JishoResult.fromJson(result))
.toList());
}
Map<String, dynamic> toJson() => {
'meta': meta.toJson(),
'data': data
};
}
Map<String, dynamic> toJson() => {'meta': meta.toJson(), 'data': data};
}

View File

@ -21,19 +21,23 @@ List<String> _getMostRecentWordTypes(Element child) {
}
List<KanjiKanaPair> _getOtherForms(Element child) {
return child.text.split('')
.map((s) => s.replaceAll('', '').replaceAll('', '').split(' '))
.map((a) => (KanjiKanaPair( kanji: a[0], kana: (a.length == 2) ? a[1] : null ))).toList();
return child.text
.split('')
.map((s) => s.replaceAll('', '').replaceAll('', '').split(' '))
.map((a) =>
(KanjiKanaPair(kanji: a[0], kana: (a.length == 2) ? a[1] : null)))
.toList();
}
List<String> _getNotes(Element child) => child.text.split('\n');
String _getMeaning(Element child) => child.querySelector('.meaning-meaning').text;
String _getMeaning(Element child) =>
child.querySelector('.meaning-meaning').text;
String _getMeaningAbstract(Element child) {
final meaningAbstract = child.querySelector('.meaning-abstract');
if (meaningAbstract == null) return null;
for (var element in meaningAbstract.querySelectorAll('a')) {
element.remove();
}
@ -62,11 +66,14 @@ List<String> _getSeeAlsoTerms(List<String> supplemental) {
}
List<PhraseScrapeSentence> _getSentences(Element child) {
final sentenceElements = child.querySelector('.sentences')?.querySelectorAll('.sentence');
final sentenceElements =
child.querySelector('.sentences')?.querySelectorAll('.sentence');
if (sentenceElements == null) return [];
final List<PhraseScrapeSentence> sentences = [];
for (var sentenceIndex = 0; sentenceIndex < (sentenceElements?.length ?? 0); sentenceIndex += 1) {
for (var sentenceIndex = 0;
sentenceIndex < (sentenceElements?.length ?? 0);
sentenceIndex += 1) {
final sentenceElement = sentenceElements[sentenceIndex];
final english = sentenceElement.querySelector('.english').text;
@ -79,20 +86,15 @@ List<PhraseScrapeSentence> _getSentences(Element child) {
final japanese = sentenceElement.text;
sentences.add(
PhraseScrapeSentence(
english: english,
japanese: japanese,
pieces: pieces ?? []
)
);
sentences.add(PhraseScrapeSentence(
english: english, japanese: japanese, pieces: pieces ?? []));
}
return sentences;
}
PhrasePageScrapeResult _getMeaningsOtherFormsAndNotes(Document document) {
final returnValues = PhrasePageScrapeResult( otherForms: [], notes: [] );
final returnValues = PhrasePageScrapeResult(otherForms: [], notes: []);
final meaningsWrapper = document.querySelector('.meanings-wrapper');
if (meaningsWrapper == null) return PhrasePageScrapeResult(found: false);
@ -102,18 +104,17 @@ PhrasePageScrapeResult _getMeaningsOtherFormsAndNotes(Document document) {
final List<PhraseScrapeMeaning> meanings = [];
var mostRecentWordTypes = [];
for (var meaningIndex = 0; meaningIndex < meaningsChildren.length; meaningIndex += 1) {
for (var meaningIndex = 0;
meaningIndex < meaningsChildren.length;
meaningIndex += 1) {
final child = meaningsChildren[meaningIndex];
if (child.className.contains('meaning-tags')) {
mostRecentWordTypes = _getMostRecentWordTypes(child);
} else if (mostRecentWordTypes[0] == 'other forms') {
returnValues.otherForms = _getOtherForms(child);
} else if (mostRecentWordTypes[0] == 'notes') {
returnValues.notes = _getNotes(child);
} else {
final meaning = _getMeaning(child);
final meaningAbstract = _getMeaningAbstract(child);
@ -153,4 +154,4 @@ PhrasePageScrapeResult parsePhrasePageData(String pageHtml, String query) {
result.tags = _getTags(document);
return result;
}
}

View File

@ -1,7 +1,6 @@
import './base_uri.dart';
/// Provides the URI for a phrase search
String uriForPhraseSearch(String phrase) {
return '$JISHO_API?keyword=${Uri.encodeComponent(phrase)}';
}
}