c#代碼 天氣接口 一分鐘搞懂你的博客爲何沒人看 看完python這段爬蟲代碼,java流淚了c#沉默了 圖片二進制轉換與存入數據庫相關 C#7.0--引用返回值和引用局部變量 JS直接調用C#後臺

天氣預報的程序。程序並不難。html

看到這個需求第一個想法就是隻要找到合適天氣預報接口一切都是小意思,說幹就幹,立馬跟學生溝通價格。java


 

​不過談報價的過程當中,差點沒讓我一口老血噴鍵盤上,話說咱們程序猿的人工何時這麼低廉了。。。oh my godpython


​50十塊,你跟我開什麼國際玩笑!!不夠意外驚喜仍是有的,竟然是個妹子嘿嘿,哎呀什麼錢不錢的多傷感情。git

老哥送你一套代碼,小妹妹之後你好好學習,不懂得問老哥,而後順利的家了微信(妹子很漂亮)。github


廢話很少說開幹,這個程序最大的難點就是找一個合適的天氣預報接口,之前沒有作過相似的程序,致使70%時間浪費在找接口以及調試接口上,不過也算我運氣好,找到了一個免費接口,接口的技術兄弟人也超棒,大大的贊。ajax

在這裏分享給你們 https://www.tianqiapi.com/?action=doc(剛兩天界面就改版了,差點覺得我訪問錯了)。sql

做爲一個免費的接口,數據詳細到這種程度,大大的良心,應付一個大學生的期末做業,簡直大材小用。chrome

 


找接口後,立馬開始寫代碼,因爲女學生要的緊,哦,不催得緊,因此代碼一切從簡,只保留核心功能,錦上添花的東西一概不要,首先搞定http請求類。數據庫

複製代碼
    public class HttpHelper
    {
        /// <summary>
        /// 發送請求的方法
        /// </summary>
        /// <param name="Url">地址</param>
        /// <param name="postDataStr">數據</param>
        /// <returns></returns>
        private string HttpPost(string Url, string postDataStr)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = Encoding.UTF8.GetByteCount(postDataStr);
            Stream myRequestStream = request.GetRequestStream();
            StreamWriter myStreamWriter = new StreamWriter(myRequestStream,         
            Encoding.GetEncoding("gb2312"));
            myStreamWriter.Write(postDataStr);
            myStreamWriter.Close();

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();

            return retString;
        }

        public string HttpGet(string Url, string postDataStr)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (postDataStr == "" ? "" : "?") + postDataStr);
            request.Method = "GET";
            request.ContentType = "text/html;charset=UTF-8";

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();

            return retString;
        }

    }
複製代碼

 

http請求搞定,接下來獲取全部的城市,主要爲了效驗用戶的輸入,不可能你輸入什麼我都去查天氣,就算你是女學生也不行,你們夥說對不?json

https://cdn.huyahaha.com/tianqiapi/city.json 全國全部城市接口。

https://www.tianqiapi.com/api/ 天氣接口,下爲參數列表。

參數 名稱 備註
version 版本標識 必填字段 目前可用值: v1
callback jsonp參數 如: jQuery.Callbacks
如下參數三選一
cityid 城市編號 如: 101120201
city 城市名稱 如: 海淀,青島,大連 (不要帶市和區)
ip IP地址 此IP地區的天氣

你們能夠自行查看下接口的返回值,簡直詳細到喪心病狂。

添加幾個model類用來序列化json

複製代碼
    public class City
    {
        public string cityZh { get; set; }
        public string id { get; set; }
    }
    public class Data
    {
        public string day { get; set; }
        public string date { get; set; }
        public string week { get; set; }
        public string wea { get; set; }
        public string air { get; set; }
        public string air_level { get; set; }
        public string air_tips { get; set; }

        public string tem { get; set; }
        public string tem1 { get; set; }
        public string tem2 { get; set; }

        public string win_speed { get; set; }
    }
    public class Weather
    {
        public string cityid { get; set; }
        public string update_time { get; set; }
        public string city { get; set; }

        public List<Data> data { get; set; }
    }
複製代碼

 

準備工做完成,開始調用接口,因爲只有兩個接口,接口文檔又很清楚,對方技術兄弟也很給力。沒費什麼勁接口調試成功,因而寫了下面兩個方法。

複製代碼
    public class Weather
    {
        HttpHelper http = new HttpHelper();
        List<City> citys = new List<City>();

        public model.Weather GetWeather(string name)
        {
            if (!citys.Any(a => a.cityZh == name.Trim()))
            {
                throw new KeyNotFoundException("未找到相關城市,請您檢查城市名");
            }
            var data = http.HttpGet($"https://www.tianqiapi.com/api/?version=v1&city={name}", "").TrimStart('(');
            return JsonConvert.DeserializeObject<model.Weather>(data);
        }

        public void GetCity()
        {
            var data = http.HttpGet("  https://cdn.huyahaha.com/tianqiapi/city.json", "");
            citys = JsonConvert.DeserializeObject<List<City>>(data);
        }
    }
複製代碼

 

而後就是界面設計,爲了省時間沒有使用更強大的wpf,而使用更簡單快捷的winform5分鐘界面擼完。

爲了方便連控件名都沒有改(若是在公司這麼作,codereview必定會被罵)label3顯示當前城市,6個groupbox爲6天的天氣,一個查詢一個退出,界面搞定。


而後編寫按鈕事件,綁定數據,沒什麼難度。

複製代碼
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
            AllCity();
        }
        Weather weather = new Weather();

        private void Form1_Load(object sender, EventArgs e)
        {
            BindData(city_name.Text.Trim());
        }

        private void AllCity()
        {
            weather.GetCity();
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void select_Click(object sender, EventArgs e)
        {

            BindData(city_name.Text.Trim());
        }

        private void BindData(string city)
        {
            model.Weather w = null;
            try
            {
                w = weather.GetWeather(city);
            }
            catch (KeyNotFoundException ex)
            {
                MessageBox.Show(ex.Message);
            }
            catch (Exception)
            {
                MessageBox.Show("查詢失敗請重試");
            }
            if (w != null)
            {
                SetView(w);
            }
        }
        private void SetCurrentCity(string city)
        {
            label3.Text = city;
        }
        private void SetView(model.Weather model)
        {
            SetCurrentCity(model.city);
            SetLable(model.data);
            SetGroupBox(model.data);
        }

        private void SetLable(List<Data> model)
        {
            var d = model[0];
            label2.Text = WeaderString(model[0]);
            label4.Text = WeaderString(model[1]); ;
            label5.Text = WeaderString(model[2]); ;
            label6.Text = WeaderString(model[3]); ;
            label7.Text = WeaderString(model[4]); ;
            label8.Text = WeaderString(model[5]); ;
        }
        private string WeaderString(Data d)
        {
            string txt = $"日期:{d.date}\r\n天氣:{d.wea}\r\n當前溫度:{d.tem}\r\n溫度:{d.tem1} - {d.tem2}\r\n空氣質量:{d.air_level}\r\n空氣指數:{d.air}\r\n風力:{d.win_speed}";
            return txt;
        }
        private void SetGroupBox(List<Data> model)
        {
            groupBox1.Text = model[0].week;
            groupBox2.Text = model[1].week;
            groupBox3.Text = model[2].week;
            groupBox4.Text = model[3].week;
            groupBox5.Text = model[4].week;
            groupBox6.Text = model[5].week;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
    }
複製代碼

 

搞定了,來看下運行效果,界面雖然簡單但是功能完美實現。


 

代碼下載 https://pan.baidu.com/s/1jOX52_w3VEgGBEPkLbOXXw

 

 

一分鐘搞懂你的博客爲何沒人看

 

  關於博客訪問量的問題,影響因素有不少,例如你的權重,你的博客數量,包括你的標題是否吸引人都是一個衡量的標準。

這些東西須要的是日積月累,今天咱們從其中的一個維度入手:發帖時間。相信你們都明白,不管是csdn,博客園這種技術博客

仍是今日頭條百度貼吧或者抖音快手這種娛樂論壇,都有本身的在線高峯期。例如百度貼吧,用戶年齡段廣泛偏小,「夜貓子」佔據主力。

21-23點是在線高峯期,這個時間的閱讀量以及評論量也是最多的,自媒體人確定會選擇在這個時間發帖已獲得更多的閱讀及評論。

 

  那咱們的博客園呢?目前咱們還不知道,既然園子裏面都是程序猿,數據統計咱就要拿出點技術人員該有的樣子,接下來咱們

寫一個爬蟲統計全部的發帖時間以及閱讀數量。

  所需語言:

    python

    c#

    sql server

  • 爬取數據

咱們打開博客園首頁,首頁的文章列表有發帖時間,閱讀數,博客園最多隻有200頁,咱們只要將這200頁的全部文章閱讀數,發帖時間爬取到就ok。

 

下面咱們用python+scrapy 來編寫爬蟲代碼。

環境配置:

pip install scrapy 安裝爬蟲框架,scrapy安裝容易遇到坑,scrapy教程與常見坑,不懂scrapy看連接。

scrapy startproject csblog 建立項目

scrapy gensider scblogSpider 「csblogs.com」 建立爬蟲文件

修改csblog下面的items.py

title:文章標題

read:閱讀數

date:發帖時間

複製代碼
# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class CnblogsItem(scrapy.Item):
    title = scrapy.Field()
    read = scrapy.Field()
    date = scrapy.Field()
複製代碼

 

而後咱們編寫爬蟲代碼,首先審查下首頁的html結構。

首先吐槽下翻頁遇到的坑,https://www.cnblogs.com/#p4,表面看上去#p4是頁碼,可是屢次嘗試變化頁碼爬取,都無效果,始終爲第一頁。

通過調試工具查看請求才發現,這個url是被重寫過得,想要翻頁得這麼發請求。

 

接下來就容易多了,向這個地址發請求,在返回的html中取得相應的數據就行了,貼代碼。

 

複製代碼
# -*- coding: utf-8 -*-
import scrapy
from cnblogs.items import CnblogsItem

class CsblogSpider(scrapy.Spider):
    name = 'csblog'
    allowed_domains = ['cnblogs.com']
    start_urls= ['https://www.cnblogs.com/mvc/AggSite/PostList.aspx']

    PageIndex = 1
    

    def start_requests(self):     
        url = self.start_urls[0]
        #由於博客園只容許200頁
        for each in range(1,200):
            print("抓取頁碼")
            print(each)
            post_data ={
                'CategoryId':'808',
                'CategoryType':"SiteHome",
                'ItemListActionName':"PostList",
                'PageIndex':str(each),
                'ParentCategoryId':'0',
                'TotalPostCount':'400'
                

                }
            yield scrapy.FormRequest(url=url, formdata=post_data)


    def parse(self, response):
        items = []
        #全部文章都在<div class="post_item">中
        for each in response.xpath("/html/body/div[@class='post_item']"):
            #提取標題
            title = each.xpath('div[@class="post_item_body"]/h3/a/text()').extract()
            #提取發佈日期
            date = each.xpath('div[@class="post_item_body"]/div/text()').extract()
            #提取閱讀數
            read = each.xpath('div[@class="post_item_body"]/div/span[@class="article_view"]/a/text()').extract()
            title = title[0]
            #去除無用的字符
            date = str(date).replace("['                    \\r\\n    ', ' \\r\\n",'').replace(" \\r\\n    ']","").replace("發佈於 ","").lstrip()
            read = read[0].replace("閱讀(","").replace(")","")


            
            item = CnblogsItem()
            item['title'] = title
            item['read'] = read
            item['date'] = date
            items.append(item)


        
        return items
            
     
複製代碼

 

 爬蟲的代碼很簡單,這也是python的強大之處。

運行 scrapy crawl csblog -o data.xml 將爬取到的數據保存爲xml。

 

咱們已經將抓取到的數據保存到本地xml了,接下來要作的事情就是數據統計了。所謂「術業有專攻」,作統計沒有比sql 更強大的語言了,python的任務到此結束。

  • 數據存儲

爲了方便的對數據進項統計查詢,咱們把xml保存到MS Sql Server中,作個這個事情沒有比Sql server的老夥計C#更合適的了,沒啥好說的簡簡單單的幾個方法。

複製代碼
     static void Main(string[] args)
        {
            data d = (data)Deserialize(typeof(data), File.OpenRead(@"D:/MyCode/cnblogs/cnblogs/data.xml"));
            DataTable dt = ToDataTable<data.item>(d.items);
            dt.TableName = "t_article";
            dt.Columns.Remove("date");
            SqlHelper.ExecuteNonQuery(dt);
        }

        /// <summary>
        /// Convert a List{T} to a DataTable.
        /// </summary>
        private static DataTable ToDataTable<T>(List<T> items)
        {
            var tb = new DataTable(typeof(T).Name);
            PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (PropertyInfo prop in props)
            {
                Type t = GetCoreType(prop.PropertyType);
                tb.Columns.Add(prop.Name, t);
            }
            foreach (T item in items)
            {
                var values = new object[props.Length];

                for (int i = 0; i < props.Length; i++)
                {
                    values[i] = props[i].GetValue(item, null);
                }

                tb.Rows.Add(values);
            }
            return tb;
        }

        /// <summary>
        /// Determine of specified type is nullable
        /// </summary>
        public static bool IsNullable(Type t)
        {
            return !t.IsValueType || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));
        }

        /// <summary>
        /// Return underlying type if type is Nullable otherwise return the type
        /// </summary>
        public static Type GetCoreType(Type t)
        {
            if (t != null && IsNullable(t))
            {
                if (!t.IsValueType)
                {
                    return t;
                }
                else
                {
                    return Nullable.GetUnderlyingType(t);
                }
            }
            else
            {
                return t;
            }
        }
        /// 反序列化  
        /// </summary>  
        /// <param name="type"></param>  
        /// <param name="xml"></param>  
        /// <returns></returns>  
        public static object Deserialize(Type type, Stream stream)
        {
            XmlSerializer xmldes = new XmlSerializer(type);
            return xmldes.Deserialize(stream);
        }
複製代碼

 

數據已經成功的存儲到sql server,接下來的數據統計是重頭戲了。

  • 數據統計
--200頁碼帖子總數量
select COUNT(*) from t_article

複製代碼
--查詢的哪一個時間段閱讀量最多
--查詢結果顯示早9點閱讀量是最多的,並不意外
--而早6點(5180)與7點(55144)相差了近10倍
--7點與8點相比差了也有三倍,這說明程序猿們陸續
--開始上班了,上班敲代碼必定是查資料的高峯期,
--果不其然,8,9,10,11,15,16是閱讀量最高峯的幾個時間段
--都分佈在上班時間,而出乎意料的事22點的閱讀量也不低
--看來程序猿們回家後也很努力的嘛(應該是在加班)
select 
CONVERT(INT, CONVERT(varchar(2),time, 108)) as count,
SUM([read]) as [read]
from t_article 
group by 
CONVERT(INT, CONVERT(varchar(2),time, 108)) 
order by [read] desc
複製代碼

 

複製代碼
--查詢閱讀量在一個星期內的分佈狀況
--結果一點都不意外,星期三比另六天
--高得多,星期一到星期五是工做日
--天天的閱讀量都很高,週末閱讀量下滑
--的厲害,由於休息了嘛(竟然沒在加班)
select 
datename(weekday, time) as weekday,
SUM([read]) as [read]
from t_article 
group by 
datename(weekday, time) 
order by [read] desc
複製代碼

 

 

 

複製代碼
--按照閱讀數量排行
--閱讀數量與發帖時間基本成正比
--這意味着,你辛辛苦苦寫的文章
--沒人看,沒有關係。時間不會辜負你
select 
CONVERT(varchar(100), time, 111),
sum([read])
from t_article 
group by CONVERT(varchar(100), time, 111)
order by sum([read])
複製代碼

 

  • 總結


閱讀的最高峯時段是早9點,因此這也是發帖的最優時間,8,9,10都是不錯的時間,若是你想要更多的閱讀,不要錯過呦。

閱讀數量最少的是星期六跟星期日,這兩天能夠不用發帖了,能夠給本身放個假。

閱讀數量會隨着時間慢慢變多,也就是說一開始沒有閱讀也不要緊,只要帖子裏有乾貨,隨着時間推移依然還會有許多閱讀從搜索引擎跳轉過來,閱讀量會慢慢上去的。

源碼以及數據庫下載地址

 

 

看完python這段爬蟲代碼,java流淚了c#沉默了

 

哈哈,其實很簡單,寥寥幾行代碼網頁爬一部小說,不賣關子,馬上開始。

首先安裝所需的包,requests,BeautifulSoup4

控制檯執行

pip install requests

pip install BeautifulSoup4

若是不能正確安裝,請檢查你的環境變量,至於環境變量配置,在這裏再也不贅述,相關文章有不少。

兩個包的安裝命令都結束後,輸入pip list

能夠看到,兩個包都成功安裝了。

好的,咱們馬上開始編寫代碼。

咱們的目標是抓取這個連接下全部小說的章節 https://book.qidian.com/info/1013646681#Catalog

咱們訪問頁面,用chrome調試工具查看元素,查看各章節的html屬性。咱們發現全部章節父元素是<ul class="cf">這個元素,章節的連接以及標題,在子<li>下的<a>標籤內。

 

那咱們第一步要作的事,就是要提取全部章節的連接。

複製代碼
'用於進行網絡請求'
import requests


chapter = requests.get("https://book.qidian.com/info/1013646681#Catalog")
print(chapter.text)
複製代碼

 

頁面順利的請求到了,接下來咱們從頁面中抓取相應的元素

複製代碼
'用於進行網絡請求'
import requests
'用於解析html'
from bs4 import BeautifulSoup


chapter = requests.get("https://book.qidian.com/info/1013646681#Catalog")

ul_bs = BeautifulSoup(chapter.text)
'提取class爲cf的ul標籤'
ul = ul_bs.find_all("ul",class_="cf")
print(ul)
複製代碼

 

ul也順利抓取到了,接下來咱們遍歷<ul>下的<a>標籤取得全部章節的章節名與連接

複製代碼
'用於進行網絡請求'
import requests
'用於解析html'
from bs4 import BeautifulSoup


chapter = requests.get("https://book.qidian.com/info/1013646681#Catalog")

ul_bs = BeautifulSoup(chapter.text)
'提取class爲cf的ul標籤'
ul = ul_bs.find_all("ul",class_="cf")
ul_bs = BeautifulSoup(str(ul[0]))
'找到<ul>下的<a>標籤'
a_bs = ul_bs.find_all("a")
'遍歷<a>的href屬性跟text'
for a in a_bs:
    href = a.get("href")
    text = a.get_text()
    print(href)
    print(text)
複製代碼

ok,全部的章節連接搞定,咱們去看想一想章節詳情頁面長什麼樣,而後咱們具體制定詳情頁面的爬取計劃。

打開一個章節,用chrome調試工具審查一下。文章標題保存在<h3 class="j_chapterName">中,正文保存在<div class="read-content j_readContent">中。

咱們須要從這兩個標籤中提取內容。

 

複製代碼
'用於進行網絡請求'
import requests
'用於解析html'
from bs4 import BeautifulSoup


chapter = requests.get("https://book.qidian.com/info/1013646681#Catalog")

ul_bs = BeautifulSoup(chapter.text)
'提取class爲cf的ul標籤'
ul = ul_bs.find_all("ul",class_="cf")
ul_bs = BeautifulSoup(str(ul[0]))
'找到<ul>下的<a>標籤'
a_bs = ul_bs.find_all("a")

detail = requests.get("https:"+a_bs[0].get("href"))
text_bs = BeautifulSoup(detail.text)
text = text_bs.find_all("div",class_ = "read-content j_readContent")
print(text)
複製代碼

正文頁很順利就爬取到了,以上代碼僅是用第一篇文章作示範,經過調試文章已經能夠爬取成功,全部下一步咱們只要把全部連接遍歷逐個提取就行了

複製代碼
'用於進行網絡請求'
import requests
'用於解析html'
from bs4 import BeautifulSoup


chapter = requests.get("https://book.qidian.com/info/1013646681#Catalog")

ul_bs = BeautifulSoup(chapter.text)
'提取class爲cf的ul標籤'
ul = ul_bs.find_all("ul",class_="cf")
ul_bs = BeautifulSoup(str(ul[0]))
'找到<ul>下的<a>標籤'
a_bs = ul_bs.find_all("a")

'遍歷全部<href>進行提取'

for a in a_bs:
    detail = requests.get("https:"+a.get("href"))
    d_bs = BeautifulSoup(detail.text)
    '正文'
    content = d_bs.find_all("div",class_ = "read-content j_readContent")
    '標題'
    name = d_bs.find_all("h3",class_="j_chapterName")[0].get_text()
    
複製代碼

在上圖中咱們看到正文中的每個<p>標籤爲一個段落,提取的文章包含不少<p>標籤這也是咱們不但願的,接下來去除p標籤。

可是去除<p>標籤後文章就沒有段落格式了呀,這樣的閱讀體驗很不爽的,咱們只要在每一個段落的結尾加一個換行符就行了

複製代碼
'用於進行網絡請求'
import requests
'用於解析html'
from bs4 import BeautifulSoup


chapter = requests.get("https://book.qidian.com/info/1013646681#Catalog")

ul_bs = BeautifulSoup(chapter.text)
'提取class爲cf的ul標籤'
ul = ul_bs.find_all("ul",class_="cf")
ul_bs = BeautifulSoup(str(ul[0]))
'找到<ul>下的<a>標籤'
a_bs = ul_bs.find_all("a")

'遍歷全部<href>進行提取'

for a in a_bs:
    detail = requests.get("https:"+a.get("href"))
    d_bs = BeautifulSoup(detail.text)
    '正文'
    content = d_bs.find_all("div",class_ = "read-content j_readContent")
    '標題'
    name = d_bs.find_all("h3",class_="j_chapterName")[0].get_text()
    
    txt = ""
    p_bs = BeautifulSoup(str(content))
    '提取每一個<p>標籤的內容'
    for p in p_bs.find_all("p"):
        txt = txt + p.get_text()+"\r\n"
複製代碼

 

去掉<p>標籤了,全部的工做都作完了,咱們只要把文章保存成一個txt就能夠了,txt的文件名以章節來命名。

複製代碼
'用於進行網絡請求'
import requests
'用於解析html'
from bs4 import BeautifulSoup

def create_txt(path,txt):
    fd = None 
    try:
        fd = open(path,'w+',encoding='utf-8')
        fd.write(txt)
    except:
        print("error")
    finally:
        if (fd !=None):
            fd.close()


chapter = requests.get("https://book.qidian.com/info/1013646681#Catalog")

ul_bs = BeautifulSoup(chapter.text)
'提取class爲cf的ul標籤'
ul = ul_bs.find_all("ul",class_="cf")
ul_bs = BeautifulSoup(str(ul[0]))
'找到<ul>下的<a>標籤'
a_bs = ul_bs.find_all("a")

'遍歷全部<href>進行提取'

for a in a_bs:
    detail = requests.get("https:"+a.get("href"))
    d_bs = BeautifulSoup(detail.text)
    '正文'
    content = d_bs.find_all("div",class_ = "read-content j_readContent")
    '標題'
    name = d_bs.find_all("h3",class_="j_chapterName")[0].get_text()

    path = 'F:\\test\\'
    path = path + name+".txt"
    
    txt = ""
    p_bs = BeautifulSoup(str(content))
    '提取每一個<p>標籤的內容'
    for p in p_bs.find_all("p"):
        txt = txt + p.get_text()+"\r\n"

    create_txt(path,txt)
    print(path+"保存成功")
複製代碼

 

 

 

圖片二進制轉換與存入數據庫相關

 

關於轉換問題,剛開始我須要從數據庫讀出一個二進制數據流,並將其轉換成一個Image格式。

在不涉及數據庫的狀況下,我先將一個圖片轉換成一個二進制數組顯示出來,再寫一個方法將其轉換成圖片image格式。

1、 先不涉及數據庫,將圖片轉換成二進制,在將二進制轉換成圖片。

複製代碼
1.protected void Button1_Click(object sender, EventArgs e)
  {
  string str = null;
  PictureToBinary ptb = new PictureToBinary();
  // str = Convert.ToBase64String( ptb.Data("E:/workspace/asp/TEST/PictureTurnToBinary/PictureTurnToBinary/img/Tulips.jpg"));

  Image newImage = Image.FromFile(Server.MapPath("Tulips.jpg"));
  str =Convert.ToBase64String( ptb.PhotoImageInsert(newImage));
  Label1.Text = str;
//label能夠用response代替(response.write(str);)
 
       

 

  }

 

複製代碼

 

第一步,我將圖片轉換成二進制數組,並轉換成string格式,用一個Label展示(也能夠用Response直接輸出到頁面顯示)。產生的數組並非二進制構成的數據流而是一串字節,以下:

因此建議先將圖片壓縮一下,否則會很大。

第二步,將獲得的二進制字節碼轉換爲圖片格式。

複製代碼
2. protected void Button2_Click(object sender, EventArgs e)
   {
     PictureToBinary ptb = new PictureToBinary();
     Image newImage = Image.FromFile(Server.MapPath("Tulips.jpg"));
     WritePhoto(ptb.PhotoImageInsert(newImage));
   }
//圖片輸出到頁面
 public void WritePhoto(byte[] streamByte)
   {
     Response.ContentType = "image/JPEG";
     Response.BinaryWrite(streamByte);
  }
複製代碼
 public class PictureToBinary
  {

    public PictureToBinary()
    {
      //
      // TODO: 在此處添加構造函數邏輯
      //

   }

public byte[] PhotoImageInsert(System.Drawing.Image imgPhoto)
  {
  //將Image轉換成二進制流數據

  MemoryStream mstream = new MemoryStream();
  imgPhoto.Save(mstream, System.Drawing.Imaging.ImageFormat.Bmp);
  byte[] myData = new Byte[mstream.Length];
    mstream.Position = 0;
  mstream.Read(myData, 0, myData.Length);
    mstream.Close();
  return myData;
  }
}
複製代碼
 
       

 

 
       
複製代碼

 

結果以下:

 

 2、將獲得的二進制數據保存到數據庫,再將其讀出。

 須要用到這麼幾個控件:一個fileLoad控件,兩個按鈕,分別是存入和讀取。

存入圖片到數據庫:

複製代碼
protected void Saveintodatabase_Click(object sender, EventArgs e)
{
  //將圖片保存到數據庫
  //加載文件,並以字節數組格式存入數據庫
  HttpPostedFile loadPhoto = FileUpload1.PostedFile;
  //獲取記載圖片內容長度
  int photoLength = loadPhoto.ContentLength;
  //存爲字節數組
  byte[] photoArray = new byte[photoLength];
  Stream photoStream = loadPhoto.InputStream;
  photoStream.Read(photoArray, 0, photoLength);
  //鏈接數據庫讀取文件
  SqlConnection conn = new SqlConnection();
  conn.ConnectionString = "Data Source=localhost;Database=Test;User Id=sa;Pwd=123456789";
  string sql = "insert into Test_Picture values(@image,3)";
  SqlCommand cmd = new SqlCommand(sql,conn);
  cmd.CommandType = System.Data.CommandType.Text;
  cmd.Parameters.Add("@image",SqlDbType.Image);
  cmd.Parameters["@image"].Value = photoArray;
  conn.Open();
  //執行sql,成功執行返回1,不然返回0(insert,update,delete),其餘命令返回-1
  int row = cmd.ExecuteNonQuery();
  Response.Write(row);
  conn.Close();
}
複製代碼

 

讀取文件:

複製代碼
protected void PhotoShowInWebSite_Click(object sender, EventArgs e)
{
  //讀取數據庫圖片文件,並保存到本地。
  SqlConnection conn = new SqlConnection();
  conn.ConnectionString = "Data Source=localhost;Database=Test;User Id=sa;Pwd=123456789";

  //選擇你須要的字段值,這邊就直接賦值了
  string sql = "select Picture from Test_Picture where Number = 3";
  SqlCommand cmd = new SqlCommand(sql, conn);
  byte[] MyData = new byte[0]; 
  try
  {
    conn.Open();
    SqlDataReader mySqlDataReader;
    mySqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
    if (mySqlDataReader.Read())
    {
      Response.Clear();

      Response.ContentType = "image/JPEG";
      Response.BinaryWrite((byte[])mySqlDataReader["Picture"]);

      /*將圖片寫入到本地d盤      

      //圖片字節流

      MyData = (byte[])mySqlDataReader["Picture"];

      int ArraySize = MyData.GetUpperBound(0);
      FileStream fs = new FileStream(@"d:\02.jpg", FileMode.OpenOrCreate, FileAccess.Write);
      fs.Write(MyData, 0, ArraySize);
      fs.Close();

      */

    }
    
  } catch (SqlException SQLexc)
  {
    Response.Write(SQLexc.ToString());
  }

    conn.Close();
}
複製代碼

 

 

以上爲整理的爲圖片二進制轉換與存取數據庫相關的內容。

 

 

C#7.0--引用返回值和引用局部變量

 

1、在C#7.0以上版本中,方法的返回值能夠經過關鍵字ref指定爲返回變量的引用(而不是值)給調用方,這稱爲引用返回值(Reference Return Value,或ref returns);
  1.與引用參數同樣,使用關鍵字ref聲明引用返回值:

public ref int MyFunc(int[] nums)
{
    //do…
    return ref nums[0];
}

  2.使用引用返回值避免了值類型在方法返回時的淺拷貝操做,提升了效率;

  3.使用引用返回值一般是爲了讓調用方有權訪問(和修改)此變量,所以引用返回值不支持無返回值方法(即返回值類型爲void);
引用返回值所返回變量指向對象的生命週期必須大於方法,即不能返回指向值類型局部變量的變量(值類型局部變量會在方法執行完返回時進行回收),能夠返回指向引用類型局部變量的變量、傳遞給方法的引用參數、靜態字段和實例字段;

  ※引用返回值不能夠返回字面量、常量、枚舉或按值返回的方法、屬性,但能夠返回當前值爲null的符合上述條件的變量;
  ※異步方法不能使用引用返回值,由於異步方法可能會在執行還沒有完成且返回值未知時就返回;
  4.查看聲明引用返回值方法的IL代碼:

  5.在調用引用返回值的方法時,調用方能夠選擇將方法返回的變量看成按值返回或是按引用返回處理,若是是按值返回處理,則與調用普通方法同樣:

int[] myNums = new int[] { 1, 2, 3, 4, 5 };
int myNum = MyFunc(myNums);

  6.若是是按引用返回處理,則調用方須要使用引用局部變量(Reference Local Variable,或ref locals)接收,保留對方法返回變量的引用:

ref int myNum = ref MyFunc(myNums);

 

  2、可使用關鍵字ref聲明引用局部變量、初始化引用局部變量及調用引用返回值的方法:

ref int myNum = ref myNums[0]; //此時引用局部變量myNum保存的是數組myNums中索引0的內存地址

  1.使用引用局部變值避免了值類型在賦值時的淺拷貝操做,提升了效率;

  2.引用局部變量必須在聲明時進行初始化,初始化時會確認該引用局部變量的做用範圍,這個做用範圍決定該引用局部變量可否做爲引用返回值返回;
對引用局部變量的賦值操做,將直接改變該變量所指向內存地址中對象的值:

myNum = 10;
Console.WriteLine(myNums[0]); //10

  3.對引用局部變量的讀取操做與普通局部變量同樣,將訪問該變量所指向內存地址中對象的值:

int num = myNum + 10; //20

  4.引用局部變量能夠做爲引用參數的實參傳遞,一樣須要使用修飾符ref修飾,對於給定的方法:

public void MyFunc(ref int num) { }
//使用時:
MyFunc(ref myNum);

  5.在C#7.3以上版本中,能夠對引用局部變量從新分配其它引用:

myNum = ref MyFunc(myNums); 

  ※給引用局部變量從新分配不能改變該引用局部變量在聲明時確認的做用範圍,所以不能給一個做用範圍較大的局部引用變量賦值一個做用範圍較小的變量;

 

 

1、操做系統用進程(Processe)分隔正在執行的程序,用線程(Thread)做爲操做系統分配處理器時間的基本單元,進程上下文中能夠運行多個線程,進程的全部線程共享其虛擬地址空間,全部線程都可執行程序代碼中的任意部分,包括其餘線程正在執行的代碼;

  1.默認狀況下,.NET程序只啓動單個線程,被稱爲主線程(Primary Thread),也能夠在運行時開啓其它線程,與主線程並行同時執行代碼,這些線程被稱爲工做線程(Worker Thread);由.Net開啓和管理的線程一般稱爲託管線程(Managed Thread);

  2.託管線程又分爲前臺線程和後臺線程,二者相似,但前臺線程會阻止進程中止,然後臺線程不會,即當進程的Main方法結束後,只有在全部前臺線程都中止時,CLR纔會結束該進程,此時會對仍處於活動狀態的後臺線程調用Abort方法來結束全部後臺進程;

  ※關閉程序如遇到沒法關閉全部線程時,能夠在Main方法結束前經過如下代碼強制關閉全部線程,詳見:

System.Environment.Exit(0);

  2、在使用多線程時,不一樣線程不只能夠同時執行同一段代碼,還能夠同時訪問同一內存中的數據,因此會存在必定的數據衝突問題,稱爲爭用條件(Race Condition):

 
static int MyNum;
static int RaceConditionCount;
static void MyFunc()
{
    while (true)
    {
        if (MyNum == 0)
        {
            MyNum++;
            if (MyNum == 0)
            {
                RaceConditionCount++; //只有在出現爭用條件時纔會執行此語句
            }
        }
        MyNum = 0;
    }
}
static void Main(string[] args)
{
    for (int i = 0; i < 2; i++)
    {
        Thread thread = new Thread(MyFunc);
        thread.Start();
    }
    Thread.Sleep(1000);
    Console.WriteLine(RaceConditionCount); //輸出1秒內產生爭用條件的次數
    Console.Read();
} 
 

  1.對於爭用條件的發生頻率,發佈版本比調試版本的出現次數多(發佈版本編譯出的代碼被優化過並且開啓了JIT優化),多核CPU比單核CPU的出現次數多(多核CPU中多個線程能夠同時運行,單核CPU的線程調度是搶佔式的,也會出現此問題,只是次數較少);

  3、爲了不產生爭用條件,須要注意數據的同步問題,能夠經過給對象加鎖,使同一時間內只有一個線程能夠執行加鎖對象所鎖定的代碼;

 

 

 

JS直接調用C#後臺方法(ajax調用)

 

1. 先手動引用DLL或者經過NuGet查找引用,這裏提供一個AjaxPro.2.dll的下載;

2. 以後的的過程不想寫了,網上都大同小異的,直接參考之前大佬寫的:

AjaxPro2完整入門教程

 

 

 

Linq To Json

 
using Newtonsoft.Json.Linq;
複製代碼
        /// <summary>
        ///     遞歸生成部門樹
        /// </summary>
        /// <param name="depList">部門列表</param>
        /// <param name="parentId">用戶部門的父級部門Id</param>
        /// <returns></returns>
        private JArray ConvertDepartTree(IList<AspSysDepartmentDto> depList, int parentId)
        {
            var jArray = new JArray(from a in depList
                                    where a.ParentId == parentId
                                    select new JObject(
                                        new JProperty("id", a.Id),
                                        new JProperty("text", a.Name),
                                        new JProperty("children", ConvertDepartTree(depList, a.Id)
                                        )));
            return jArray;
        }
複製代碼

JSON.net Linq  To Json文檔地址:https://www.newtonsoft.com/json/help/html/CreatingLINQtoJSON.htm

 

SqlServer 遞歸查詢

 
複製代碼
--查詢部門及下屬部門列表

WITH TEMP   --遞歸
     AS (SELECT Id,
                Code,
                Name,
                ParentId
         FROM   [dbo].[AspSysDepartments]
         WHERE  Id = 38   --查詢當前部門
         UNION ALL
         SELECT B.Id,  --查詢子部門
                B.Code,
                B.Name,
                B.ParentId
         FROM   TEMP A
                INNER JOIN [dbo].[AspSysDepartments] B
                        ON B.ParentId = A.Id)
SELECT Id,
       Code,
       Name,
       ParentId
FROM   TEMP   --獲取遞歸後的集合
複製代碼

結果:

相關文章
相關標籤/搜索