12

単純な Web クローラーを作成しましたが、再帰関数を追加して、開いているすべてのページでこのページの URL を取得できるようにしたいのですが、それを行う方法がわかりません。作成するスレッドも含めたいです。それはより速く。これが私のコードです

namespace Crawler
{
    public partial class Form1 : Form
    {
        String Rstring;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            
            WebRequest myWebRequest;
            WebResponse myWebResponse;
            String URL = textBox1.Text;

            myWebRequest =  WebRequest.Create(URL);
            myWebResponse = myWebRequest.GetResponse();//Returns a response from an Internet resource

            Stream streamResponse = myWebResponse.GetResponseStream();//return the data stream from the internet
                                                                       //and save it in the stream

            StreamReader sreader = new StreamReader(streamResponse);//reads the data stream
            Rstring = sreader.ReadToEnd();//reads it to the end
            String Links = GetContent(Rstring);//gets the links only
            
            textBox2.Text = Rstring;
            textBox3.Text = Links;
            streamResponse.Close();
            sreader.Close();
            myWebResponse.Close();




        }

        private String GetContent(String Rstring)
        {
            String sString="";
            HTMLDocument d = new HTMLDocument();
            IHTMLDocument2 doc = (IHTMLDocument2)d;
            doc.write(Rstring);
            
            IHTMLElementCollection L = doc.links;
           
            foreach (IHTMLElement links in  L)
            {
                sString += links.getAttribute("href", 0);
                sString += "/n";
            }
            return sString;
        }
4

4 に答える 4

11

クロールされたページから新しいリンクを取得するために、GetContent メソッドを次のように修正しました。

public ISet<string> GetNewLinks(string content)
{
    Regex regexLink = new Regex("(?<=<a\\s*?href=(?:'|\"))[^'\"]*?(?=(?:'|\"))");

    ISet<string> newLinks = new HashSet<string>();    
    foreach (var match in regexLink.Matches(content))
    {
        if (!newLinks.Contains(match.ToString()))
            newLinks.Add(match.ToString());
    }

    return newLinks;
}

更新しました

修正済み: 正規表現は regexLink にする必要があります。これを指摘してくれた@shashlearnerに感謝します(私のミスタイプ)。

于 2012-05-10T10:49:29.287 に答える
8

Reactive Extensionを使用して同様のものを作成しました。

https://github.com/Misterhex/WebCrawler

お役に立てば幸いです。

Crawler crawler = new Crawler();

IObservable observable = crawler.Crawl(new Uri("http://www.codinghorror.com/"));

observable.Subscribe(onNext: Console.WriteLine, 
onCompleted: () => Console.WriteLine("Crawling completed"));
于 2013-06-07T02:37:27.163 に答える
2

以下には、回答/推奨事項が含まれています。

GUI で見ると、見つかったリンク (URL) が見やすいので、 a のdataGridView代わりに aを使用する必要があると思います。textBox

次のように変更できます。

textBox3.Text = Links;

 dataGridView.DataSource = Links;  

質問のために、あなたは含まれていません:

using System.  "'s"

わからないので入手できれば幸いです。

于 2012-09-13T14:33:24.653 に答える
0

設計の観点から、私はいくつかの Web クローラーを作成しました。基本的に、Stack データ構造を使用して深さ優先検索を実装します。幅優先検索も使用できますが、スタック メモリの問題が発生する可能性があります。幸運を。

于 2012-09-13T14:41:11.103 に答える