feat: initail drug crawling
This commit is contained in:
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CompilerConfiguration">
|
<component name="CompilerConfiguration">
|
||||||
<bytecodeTargetLevel target="17" />
|
<bytecodeTargetLevel target="21" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
Generated
+8
@@ -4,6 +4,14 @@
|
|||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
|
<DropdownSelection timestamp="2026-05-15T13:26:47.825150Z">
|
||||||
|
<Target type="DEFAULT_BOOT">
|
||||||
|
<handle>
|
||||||
|
<DeviceId pluginId="LocalEmulator" identifier="path=/Users/amirmahdi/.android/avd/Pixel_3a_API_33_arm64-v8a.avd" />
|
||||||
|
</handle>
|
||||||
|
</Target>
|
||||||
|
</DropdownSelection>
|
||||||
|
<DialogSelection />
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
</selectionStates>
|
</selectionStates>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
Generated
+1
-2
@@ -1,7 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
|||||||
@@ -88,4 +88,8 @@ dependencies {
|
|||||||
implementation(libs.androidx.room.runtime)
|
implementation(libs.androidx.room.runtime)
|
||||||
implementation(libs.androidx.room.ktx)
|
implementation(libs.androidx.room.ktx)
|
||||||
ksp(libs.androidx.room.compiler)
|
ksp(libs.androidx.room.compiler)
|
||||||
|
|
||||||
|
//crawl
|
||||||
|
implementation(libs.jsoup)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ import com.approagency.drug.data.dto.DarmanModel
|
|||||||
import com.approagency.drug.data.dto.DrugListResponse
|
import com.approagency.drug.data.dto.DrugListResponse
|
||||||
import com.approagency.drug.data.dto.DrugModels
|
import com.approagency.drug.data.dto.DrugModels
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.Headers
|
||||||
import retrofit2.http.Path
|
import retrofit2.http.Path
|
||||||
import retrofit2.http.Query
|
import retrofit2.http.Query
|
||||||
|
|
||||||
@@ -26,4 +27,15 @@ interface DrugApiService {
|
|||||||
|
|
||||||
@GET("drugs/goroh-darmani")
|
@GET("drugs/goroh-darmani")
|
||||||
suspend fun getGorohDaroei(): DarmanModel
|
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
|
||||||
}
|
}
|
||||||
@@ -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<DrugSearchResult> {
|
||||||
|
val document: Document = Jsoup.parse(html)
|
||||||
|
val results = mutableListOf<DrugSearchResult>()
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
|
)
|
||||||
@@ -20,8 +20,9 @@ lifecycleViewmodelKtx = "2.9.4"
|
|||||||
room = "2.6.1"
|
room = "2.6.1"
|
||||||
navigationCompose = "2.8.5"
|
navigationCompose = "2.8.5"
|
||||||
material3 = "1.4.0"
|
material3 = "1.4.0"
|
||||||
|
jsoup = "1.18.3"
|
||||||
[libraries]
|
[libraries]
|
||||||
|
jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
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-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-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" }
|
||||||
androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" }
|
androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" }
|
||||||
|
|
||||||
|
|
||||||
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
|
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
|
||||||
androidx-room-ktx = { module = "androidx.room:room-ktx", 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" }
|
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
|
||||||
|
|||||||
Reference in New Issue
Block a user