From 28f0c868d58015bc35b74447fc4357f386e67667 Mon Sep 17 00:00:00 2001 From: Amirmahdi Nourkazemi Date: Sat, 16 May 2026 23:30:16 +0330 Subject: [PATCH] feat: initail drug crawling --- .idea/compiler.xml | 2 +- .idea/deploymentTargetSelector.xml | 8 +++ .idea/misc.xml | 3 +- app/build.gradle.kts | 4 ++ .../drug/data/remote/DrugApiService.kt | 12 ++++ .../drug/data/remote/DrugHtmlParser.kt | 58 +++++++++++++++++++ .../drug/domain/model/DrugSearchResult.kt | 8 +++ gradle/libs.versions.toml | 5 +- 8 files changed, 94 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/com/approagency/drug/data/remote/DrugHtmlParser.kt create mode 100644 app/src/main/java/com/approagency/drug/domain/model/DrugSearchResult.kt diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 8fabff5..8b3f102 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml index 0d46093..1f4a86f 100644 --- a/.idea/deploymentTargetSelector.xml +++ b/.idea/deploymentTargetSelector.xml @@ -4,6 +4,14 @@ diff --git a/.idea/misc.xml b/.idea/misc.xml index f104487..b2c751a 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,7 +1,6 @@ - - + diff --git a/app/build.gradle.kts b/app/build.gradle.kts index aec1799..cb054eb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -88,4 +88,8 @@ dependencies { implementation(libs.androidx.room.runtime) implementation(libs.androidx.room.ktx) ksp(libs.androidx.room.compiler) + + //crawl + implementation(libs.jsoup) + } \ No newline at end of file diff --git a/app/src/main/java/com/approagency/drug/data/remote/DrugApiService.kt b/app/src/main/java/com/approagency/drug/data/remote/DrugApiService.kt index 0aff4cf..84dd236 100644 --- a/app/src/main/java/com/approagency/drug/data/remote/DrugApiService.kt +++ b/app/src/main/java/com/approagency/drug/data/remote/DrugApiService.kt @@ -4,6 +4,7 @@ import com.approagency.drug.data.dto.DarmanModel import com.approagency.drug.data.dto.DrugListResponse import com.approagency.drug.data.dto.DrugModels import retrofit2.http.GET +import retrofit2.http.Headers import retrofit2.http.Path import retrofit2.http.Query @@ -26,4 +27,15 @@ interface DrugApiService { @GET("drugs/goroh-darmani") suspend fun getGorohDaroei(): DarmanModel + + + @GET("Search") + @Headers( + "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36", + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Language: en-US,en;q=0.5" + ) + suspend fun searchDrugs( + @Query("SearchText") searchText: String + ): String // Returns raw HTML for the first page } \ No newline at end of file diff --git a/app/src/main/java/com/approagency/drug/data/remote/DrugHtmlParser.kt b/app/src/main/java/com/approagency/drug/data/remote/DrugHtmlParser.kt new file mode 100644 index 0000000..f940d76 --- /dev/null +++ b/app/src/main/java/com/approagency/drug/data/remote/DrugHtmlParser.kt @@ -0,0 +1,58 @@ +package com.approagency.drug.data.remote + +import com.approagency.drug.domain.model.DrugSearchResult +import okio.IOException +import org.jsoup.Jsoup +import org.jsoup.nodes.Document + +class DrugHtmlParser { + + fun parseSearchResults(html: String): List { + val document: Document = Jsoup.parse(html) + val results = mutableListOf() + + // Select the table body that contains the drug rows + val rows = document.select("#tbody_DrugList tr") + + if (rows.isEmpty()) { + // Handle case where no results are found + return emptyList() + } + + for (row in rows) { + try { + // --- Extract Persian Name and Detail Page URL --- + val nameCell = row.selectFirst("td:eq(0)") // First td + val drugLink = nameCell?.selectFirst("a.ahref_Generic") + val persianName = drugLink?.text()?.trim() ?: continue // Skip if no name found + val detailPageRelativeUrl = drugLink?.attr("href") ?: continue + val detailPageUrl = "https://www.darooyab.ir$detailPageRelativeUrl" + + // --- Extract Generic ID from URL --- + // URL format: /G-2556/Casanthranol or /G-2556/ + val genericIdRegex = "/G-(\\d+)/?".toRegex() + val genericId = genericIdRegex.find(detailPageRelativeUrl)?.groupValues?.get(1) ?: "" + + // --- Extract English Name --- + // The last cell contains the English name link + val lastCell = row.select("td").last() + val englishLink = lastCell?.selectFirst("a.ahref_Generic") + val englishName = englishLink?.text()?.trim() + + val drugResult = DrugSearchResult( + genericId = genericId, + persianName = persianName, + englishName = englishName, + detailPageUrl = detailPageUrl + ) + results.add(drugResult) + + } catch (e: Exception) { + // Log error for a specific row but continue with others + println("Error parsing row: ${e.message}") + } + } + + return results + } +} \ No newline at end of file diff --git a/app/src/main/java/com/approagency/drug/domain/model/DrugSearchResult.kt b/app/src/main/java/com/approagency/drug/domain/model/DrugSearchResult.kt new file mode 100644 index 0000000..dbf4ee5 --- /dev/null +++ b/app/src/main/java/com/approagency/drug/domain/model/DrugSearchResult.kt @@ -0,0 +1,8 @@ +package com.approagency.drug.domain.model + +data class DrugSearchResult( + val genericId: String, // e.g., "2556" from "/G-2556/Casanthranol" + val persianName: String, + val englishName: String? = null, // "Casanthranol", might be null for some entries + val detailPageUrl: String // e.g., "/G-2556/Casanthranol" or "https://www.darooyab.ir/G-2556/Casanthranol" +) \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fbbb379..394ef2d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,8 +20,9 @@ lifecycleViewmodelKtx = "2.9.4" room = "2.6.1" navigationCompose = "2.8.5" material3 = "1.4.0" - +jsoup = "1.18.3" [libraries] +jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } @@ -51,8 +52,6 @@ location-services = { group = "com.google.android.gms", name = "play-services-lo androidx-lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" } androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" } androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" } - - androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" } androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" } androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }