利用C#爬取煎蛋網圖片
阿新 • • 發佈:2018-11-20
本程式還有待優化,我只爬取了每個頁面的第一張圖片,你們可以自己更新優化程式碼以實現全站爬取的功能。
主要用到的名稱空間有:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; using System.Text.RegularExpressions; using System.Net; using System.Threading;
其中比較重要的就是Threading和Net。這兩個比較核心的。還有一個比較重要的函式就是http訪問的函式。
而且我還設定了一個進入時需要登陸的頁面來保障軟體不被非法獲得。除非你有很強的逆向技術==,不過這就另當別論了。
啟用介面核心思想:
首先用picturebox來作背景。其中新增label標籤,設定賬號密碼標題等必須屬性。增加textare來做文字域。button按鈕實現登入功能。
當button按鈕被點選時,觸發click事件。username.text和password.text的值會再後臺與資料庫的值進行校驗。(不過我懶得弄資料庫了,就直接把賬號密碼寫程序序中了。)
程式碼:
private void button1_Click(object sender, EventArgs e) { if (label1.Text == "" && label2.Text == "") { MessageBox.Show("請輸入賬號密碼.", "警告"); } else if ((textBox1.Text == "local" && textBox2.Text == "123456") || (textBox1.Text == "User" && textBox2.Text == "QzaFGkoNFasd")) { Form2 f2 = new Form2(); f2.Show(); this.Hide(); } else { MessageBox.Show("登陸失敗,請檢查賬號名和密碼。", "提示"); } }
關於資料庫的地方我就不做優化了==畢竟沒有作為商業用途的考慮,主要還是以學習研究為主。
winform登陸後的介面:
介面主要是一個picturebox和兩個控制圖片的button按鈕以及一個題目label標籤。
而下面就是核心程式碼了。
public partial class Form2 : Form
{
private int count = 0;
private List<string> image_url = new List<string>();
public Form2()
{
InitializeComponent();
this.Text = "妹妹圖";
label1.Parent = pictureBox2;
button1.Parent = pictureBox2;
button2.Parent = pictureBox2;
pictureBox1.Parent = pictureBox2;
Thread thread1 = new Thread(get_image_url);
thread1.IsBackground = true;
thread1.Start();
Thread thread2 = new Thread(set_first_image);
thread2.IsBackground = true;
thread2.Start();
}
private void set_first_image()
{
while (image_url.Count>1)
{
pictureBox1.ImageLocation = image_url[count];
break;
}
}
private bool RemoteFileExists(string fileUrl)
{
bool result = false;
WebResponse response = null;
try
{
WebRequest req = WebRequest.Create(fileUrl);
response = req.GetResponse();
result = response == null ? false : true;
}
catch (Exception ex)
{
result = false;
}
finally
{
if (response != null)
{
response.Close();
}
}
return result;
}
private string httpd_request(string url)
{
string result = "";
try
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(new Uri(url));
req.Method = "GET";
req.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0";
req.Host = "jandan.net";
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Stream stream = resp.GetResponseStream();
//獲取響應內容
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
{ result = reader.ReadToEnd(); }
}
catch (Exception esp)
{
MessageBox.Show("報錯原因:" + esp + "\r\n" + "請檢查網頁連結有無問題後重試!\r\n");
}
return result;
}
public string DecodeBase64(Encoding encode, string result)
{
string decode = "";
byte[] bytes = Convert.FromBase64String(result);
try
{
decode = encode.GetString(bytes);
}
catch
{
decode = result;
}
return decode;
}
private void get_image_url()
{
for(int i =1;i<50;i++)
{
string url = "http://jandan.net/ooxx/page-"+i.ToString();
string html = httpd_request(url);
string picture_title= Regex.Match(html, "<span class=\"img-hash\">.*?</span>").ToString();
string picture_url = "";
for (int j = 23; j < picture_title.Length - 7; j++)
{
picture_url = picture_url + picture_title[j];
}
string http_url = "http:" + (DecodeBase64(Encoding.UTF8, picture_url));
if(RemoteFileExists(http_url))
{
image_url.Add(http_url);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
if (count+1 > image_url.Count)
{
count = 0;
}
pictureBox1.ImageLocation = image_url[++count];
}
private void button2_Click(object sender, EventArgs e)
{
if (count - 1 < 0) {
count = image_url.Count;
}
pictureBox1.ImageLocation = image_url[--count];
}
}
這裡使用了可變長陣列List<string>來儲存爬蟲獲取到的url資訊。而上一張和下一張按鈕的事件觸發時只能來調整picturebox中的回顯圖片。並在後臺採用多執行緒方式持續爬取且存入陣列中。
這麼做無法保證使用者點選速度和爬取速度存在防寫的情況,可能會出現索引溢位的可能。
值得注意的是,這裡並沒有講圖片下載到本地電腦,而是直接採用picture遠端包含圖片的url連結。減少了對硬碟空間的要求。但是要求使用者的網速最好不是那麼不盡如人意。