PDA

View Full Version : سوال: تبدیل صفحه وب به جدول دیتابیس



md3848
شنبه 01 خرداد 1400, 09:46 صبح
سلام، یه سری داده ( رساله آیت الله مکارم شیرازی (https://makarem.ir/main.aspx?typeinfo=30) مثلا ) به صورت صفحه وب هستش، که میخوام تبدیلش کنم به دیتابیس، با توجه به این که بیش از 1000 صفحه هستش، امکان اشتباه در کپی پیس کردن زیاده و زمان و حوصله زیادی هم میطلبه که ... اصلا نمیخوام بهش فکر بکنم چه برسه به این که ...
خاستم ببینم راهی برا حل این مشکل دارید؟ حالت ایده آلم اینه که بشه پروژه ای با c# نوشت که اینکارو برام بکنه و بین صفحات وب پیمایش کنه و داده های اضافه رو حذف و داده های اصلی رو در جدول مربوطه صفحه به صفحه کپی کنه تا آخر...

رامین مرادی
شنبه 01 خرداد 1400, 09:59 صبح
سلام
همون روشی که فرمودید مناسبه و یه برنامه بنویسید کد html صفحه رو بگیرید و محتوای تگی که حاوی EDContent هست رو داخل دیتابیس ذخیره کنید. بعد یه ویرایش کوچولی هم نیاز داره که بجای مثلا تگ ها <> یه اینتر ریپلیس کنید. البته یه کم باید سعی و خطا کنید تا نتیجه مطلوب بدست بیارید.

md3848
شنبه 01 خرداد 1400, 10:07 صبح
Web Scraping with C Sharp
Web scraping is a technique used in any language such as C# to extract data from a website
https://html-agility-pack.net

barnamenevisjavan
شنبه 01 خرداد 1400, 12:36 عصر
سلام باید از همین htmlagilitypack استفاده کنید کار باهاش هم خیلی راحته

336699
شنبه 01 خرداد 1400, 16:23 عصر
سلام نیازی به لود صفحات html واستفاده از htmlagilitypack نیست.

شما برای بدست آوردن اطلاعات اون صفحه

باید یکسری درخواست با متد POST به آدرس
https://makarem.ir/WebServiceClient/Category.asmx/Get

ارسال کنید و نتیجه بصورت جیسون برمیگرده و با استفاده از کتابخانه Newtonsoft.Json می توانید متن جیسون را بخوانید.




عدد مربوط به CategoryID برای موضوعات مختلف متفاوت هست

لیست آیدی های مربوط به [توضیح المسائل] را از این صفحه دریافت نمایید.

https://makarem.ir/upload/tempjs/lid0_type30.js


(https://makarem.ir/upload/tempjs/lid0_type30.js)

336699
شنبه 01 خرداد 1400, 23:24 عصر
بعد از اینکه اون فایلlid0_type30.js رو دریافت کردید
با استفاده از ریجکس می توانید لیست آیدی های مربوطه را بدست بیاورید که حدود سه هزار تا میشه

یعنی باید سه هزارتا درخواست با متد پست ارسال کنید تا [توضیح المسائل] کامل داشته باشید.

string contents = File.ReadAllText("lid0_type30.js", Encoding.UTF8);

string patern = @"(?<=catalltreemenu\[)(\d+)";
Regex reg = new Regex(patern);
MatchCollection matches = reg.Matches(contents);

List<string> listCategoryID = new List<string>();

foreach (Match mat in matches)
listCategoryID.Add(mat.Value.ToString());

listCategoryID = listCategoryID.Distinct().ToList();

md3848
دوشنبه 03 خرداد 1400, 23:56 عصر
با تشکر از همه دوستان از روش زیر رفتم ( هرچند برا کارهای آینده ام احتمالا به روش آقا/خانم 336699 نیاز پیدا کنم، چون همیشه اینقدر خوششانس نیستم که سایت مرجع فوق داده هارو ... )
خود سایت مکارم، یه قسمتی داره مخصوص احکام ( این لینک (https://makarem.ir/ahkam/fa/treatise/index?page=213&sortby=0&sort=1&view=0) ) که راحت داده هاشو با کد زیر گرفتم ازش :
اینم کل رساله که با کد زیر استخراج کردم از لینک بالا : 153338

using HtmlAgilityPack;using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Windows;


namespace WpfApp6
{
public partial class MainWindow : Window
{
#region Class Model
public class Model
{
public int ID;
public int IssueNumber;
public string CategoryTitle;
public string IssueTitle;
public string IssueContent;
}


public List<Model> models = new List<Model>();
#endregion


public MainWindow()
{
InitializeComponent();


DoIt();
}


private void DoIt()
{
int ID = 0;


// Read Data from web
for (int page = 1; page <= 213; page++)
{
string html = @"https://makarem.ir/ahkam/fa/treatise/index?page=" + page + "&sortby=0&sort=1&view=0";


HtmlWeb web = new HtmlWeb();


HtmlDocument htmlDoc = web.Load(html);


var node = htmlDoc.DocumentNode.SelectSingleNode("//div[@class='card-columns']");
var IssueNumbers = node.SelectNodes("//span[@class='treatise-number']");
var CategoryTitles = node.SelectNodes("//span[@class='treatise-category']/a");
var IssueTitles = node.SelectNodes("//h3/a");
var IssueContents = node.SelectNodes("//div[@class='row']/div/p/text()");






int ItemsCount = IssueNumbers.Count;
if (CategoryTitles.Count != ItemsCount ||
IssueTitles.Count != ItemsCount ||
IssueContents.Count != ItemsCount)
{
Debug.WriteLine("ItemsCount problem in page = " + page);
continue;
}






for (int i = 0; i < ItemsCount; i++)
{
var inBuff = StringToInt(IssueNumbers[i].InnerText);
int IssueNumber = inBuff.IsSuccessful == true ? inBuff.Result : -1;


models.Add(new Model
{
ID = ID,
IssueNumber = IssueNumber,
CategoryTitle = CategoryTitles[i].InnerText,
IssueTitle = IssueTitles[i].InnerText,
IssueContent = IssueContents[i].InnerText.Replace("\n", "").Replace("\r", ""),
});


ID++;


Debug.WriteLine("page = " + page.ToString("000") + ", Items = " + (i + 1).ToString("00") + "/" + ItemsCount);
}
}






// add all data to txt file
string txtPath = @"C:\Users\mahdi\Desktop\Data.txt";
using (TextWriter tw = new StreamWriter(txtPath))
{
string data = "ID,IssueNumber,CategoryTitle,IssueTitle,IssueConte nt\r\n";


foreach (Model model in models)
{
data =
model.ID + "," +
model.IssueNumber + "," +
model.CategoryTitle + "," +
model.IssueTitle + "," +
model.IssueContent;


tw.WriteLine(data);
}
}
}


private (bool IsSuccessful, int Result) StringToInt(string data)
{
string a = data;
string b = string.Empty;


for (int i = 0; i < a.Length; i++)
{
if (char.IsDigit(a[i]))
b += a[i];
}


if (b.Length > 0)
{
return (true, int.Parse(b));
}
else
{
return (false, 0);
}
}
}
}