本程序还有待优化,我只爬取了每个页面的第一张图片,你们可以自己更新优化代码以实现全站爬取的功能。
主要用到的命名空间有:
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链接。减少了对硬盘空间的要求。但是要求用户的网速最好不是那么不尽如人意。
效果图:
|
请发表评论