結對同窗的博客地址html
本做業博客的連接python
github地址git
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | 30 | 30 |
· Estimate | · 估計這個任務須要多少時間 | 60 | 60 |
Development | 開發 | 300 | 400 |
· Analysis | · 需求分析 (包括學習新技術) | 60 | 60 |
· Design Spec | · 生成設計文檔 | 30 | 30 |
· Design Review | · 設計複審 | 30 | 30 |
· Coding Standard | · 代碼規範 (爲目前的開發制定合適的規範) | 30 | 20 |
· Design | · 具體設計 | 60 | 120 |
· Coding | · 具體編碼 | 120 | 150 |
· Code Review | · 代碼複審 | 120 | 210 |
· Test | · 測試(自我測試,修改代碼,提交修改) | 180 | 180 |
Reporting | 報告 | 60 | 80 |
· Test Repor | · 測試報告 | 20 | 20 |
· Size Measurement | · 計算工做量 | 10 | 10 |
· Postmortem & Process Improvement Plan | · 過後總結, 並提出過程改進計劃 | 30 | 20 |
合計 | 1110 | 1420 |
本次爬蟲採用python完成,代碼是本身寫的github
思路:正則表達式
爬取[CVPR2018網頁](http://openaccess.thecvf.com/CVPR2018.py)內容,用正則表達式將網頁內容中論文連接提早到字符串數組中。 遍歷數組,在每次訪問論文網頁的過程當中將論文標題和摘要爬取出來。 根據題目要求的輸出格式,將數據輸出到result.txt文件中。
代碼:算法
from bs4 import BeautifulSoup from urllib.request import urlopen import re import random filename = 'data.txt' base_url = "http://openaccess.thecvf.com/CVPR2018.py" b_url="http://openaccess.thecvf.com/" html = urlopen(base_url).read().decode('utf-8') soup = BeautifulSoup(html, features='lxml') sub_urls = soup.find_all("a", { "href": re.compile("content_cvpr_2018/html/(.)+CVPR_2018_paper.html$")}) k=len(sub_urls) print(k) with open(filename,'w',encoding='utf-8') as f: for i in range (5): his=sub_urls[i]['href'] url= b_url + his html2 = urlopen(url).read().decode('utf-8') soup2 = BeautifulSoup(html2, features='lxml') sub_urls2 = soup2.find_all("div",id="papertitle") sub_urls3 = soup2.find_all("div",id="abstract") j=str(i) f.write(j) f.write('\n') f.write("Title:"+sub_urls2[0].text.lstrip('\n')) f.write('\n') f.write("Abstract:"+sub_urls3[0].text.lstrip('\n')) f.write('\n') f.write("\n\n\n")`
因爲本次做業與我的做業2的代碼部分相同,如判斷單詞等。這裏就不贅述了。數組
部分代碼以下:網絡
int topn = 10; int word_m = 1; int word_w = 1; int i = 1; int infile=-1, outfile=-1; string in = "-i",o="-o",w="-w",m="-m",n="-n"; while (argv[i]) { if (argv[i] == in) infile = i + 1; if (argv[i] == o) outfile = i + 1; if (argv[i] == w) word_w= atoi(argv[i+1]); if (argv[i] == m) word_m = atoi(argv[i + 1]); if (argv[i] == n) topn = atoi(argv[i + 1]); i++; }
根據論文的爬取結果格式,能夠很明顯的看出,一篇論文共佔用5行,其中第二行爲"Title: "行,第三行爲"Abstract: "行dom
代碼以下:函數
if (w == 1) //賦值權重 { if (ch == '\n') { huiche++; if (huiche % 5 == 1) { while ((ch = fgetc(file)) != ':'); quanzhong = 10; } if (huiche % 5 == 2) { while ((ch = fgetc(file)) != ':'); quanzhong = 1; } } }
如何判斷是否爲一個單詞這裏就不重複了,詳見這裏
本篇重點介紹如何判斷一個詞組。
代碼以下:
string word_array[20]; int wn = 0; int re_word_num = m; for (; (ch = fgetc(file)) != EOF;) //Determine the word and insert map { if ('A' <= ch && ch <= 'Z') ch = ch + 32; if (flag == 0) { if (ch >= 'a'&&ch <= 'z') { flag = 1; word = word + ch; } else if (ch !=' ') { wn = 0; re_word_num=m; } } else if (flag == 1) { if (ch >= 'a'&&ch <= 'z') { flag = 2; word = word + ch; } else { flag = 0; word = ""; wn = 0; re_word_num = m;} } else if (flag == 2) { if (ch >= 'a'&&ch <= 'z') { flag = 3; word = word + ch; } else { flag = 0; word = ""; wn = 0; re_word_num = m;} } else if (flag == 3) { if (ch >= 'a'&&ch <= 'z') { flag = 4; word = word + ch; } else { flag = 0; word = ""; wn = 0; re_word_num = m;} } else if (flag == 4) { if (ch >= 'a'&&ch <= 'z' || (ch >= '0'&&ch <= '9')) { word = word + ch; } else { word_array[wn % 20] = word; word_num++; wn++; re_word_num--; word = ""; if (re_word_num == 0) { for (int j = m; j > 1; j--) word = word + word_array[(wn - j) % 20]+" "; word = word + word_array[(wn - 1) % 20]; Word_Num_map[word] = Word_Num_map[word] + quanzhong; re_word_num = 1; } word = ""; flag = 0; } } if (ch == '\n')//換行初始化。 { wn = 0; re_word_num = m; } if (w == 1) //賦值權重 { if (ch == '\n') { huiche++; if (huiche % 5 == 1) { while ((ch = fgetc(file)) != ':'); quanzhong = 10; } if (huiche % 5 == 2) { while ((ch = fgetc(file)) != ':'); quanzhong = 1; } } } } if (flag == 4) { re_word_num--; word_array[wn % 20] = word; wn++; if (re_word_num == 0) { word = ""; for (int j = m; j > 1; j--) word = word + word_array[(wn - j) % 30] + " "; word = word + word_array[(wn - 1) % 30]; Word_Num_map[word] = Word_Num_map[word] ++; } } vector <PAIR> Word_Num_vec(Word_Num_map.begin(), Word_Num_map.end()); sort(Word_Num_vec.begin(), Word_Num_vec.end(), CmpByValue()); FILE * stream; freopen_s(&stream, outfile, "a", stderr); if(Word_Num_vec.size()<n) for (int i = 0; i != Word_Num_vec.size(); ++i) { const char *ss = Word_Num_vec[i].first.c_str(); //cout << ss << ":" << Word_Num_vec[i].second << endl; fprintf(stream, "<%s>: %d\n", ss, Word_Num_vec[i].second); //outfile <<"<"<< ss << ">"<<":" << Word_Num_vec[i].second << endl;); } else for (int i = 0; i != n; ++i) { const char *ss = Word_Num_vec[i].first.c_str(); fprintf(stream, "<%s>: %d\n", ss, Word_Num_vec[i].second); } Word_Num_vec.clear(); fclose(file);
算法流程圖以下:
附加題及爬蟲python代碼實現和爬蟲數據文本戳這裏
思路:和前面爬摘要部分同樣,用python能夠將咱們想要的做者名字爬取下來,而後用Count函數返回出現頻率最高的十名做者。
結果展現圖:(右側是做者在頂會上發佈論文的數量)
代碼以下:
from bs4 import BeautifulSoup from urllib.request import urlopen import re import random filename = 'author.txt' base_url = "http://openaccess.thecvf.com/CVPR2018.py" b_url="http://openaccess.thecvf.com/" html = urlopen(base_url).read().decode('utf-8') soup = BeautifulSoup(html, features='lxml') sub_urls = soup.find_all("a", { "href": re.compile("content_cvpr_2018/html/(.)+CVPR_2018_paper.html$")}) k=len(sub_urls) print(k) with open(filename,'w',encoding='utf-8') as f: for i in range (k): his=sub_urls[i]['href'] url= b_url + his html2 = urlopen(url).read().decode('utf-8') soup2 = BeautifulSoup(html2, features='lxml') sub_urls2 = soup2.find_all("div",id="authors") ls=sub_urls2[0].text.split(";") f.write(ls[0].lstrip('\n')) print(i) print('yes')`
將網站中的做者名字爬出
from collections import Counter f=open('author.txt','r',encoding="utf-8") t=f.read() f.close() tx=t.strip() ls=tx.split(",") def counter(arr): return Counter(arr).most_common(10) # 返回出現頻率最高的十個做家 author=counter(ls) for i in range(10): print(author[i])`
將出現頻率最高的十個做者打印出
前面已經將論文做者的名字爬下來了,可視化部分用python的wordcloud庫能夠很輕易地實現這一功能
效果圖以下:
代碼以下:
import wordcloud f=open('author.txt','r',encoding="utf-8") t=f.read() f.close() tx=t.replace(' ','') ls=tx.split(",") txt=" ".join(ls) w=wordcloud.WordCloud(width=1000,height=700) w.generate(txt) w.to_file("author.png") filename = 'authorall.txt' with open(filename,'w',encoding='utf-8') as f: f.write(txt)`
用戶在查看摘要的過程當中,若是感興趣,就能夠憑這個連接直接下載論文的pdf或者在線閱讀,本功能也可用Excel來存儲,更爲直觀
效果圖:
代碼以下:
from bs4 import BeautifulSoup` from urllib.request import urlopen` import re` import random` filename = 'data.txt'` base_url = "http://openaccess.thecvf.com/CVPR2018.py"` b_url="http://openaccess.thecvf.com/"` html = urlopen(base_url).read().decode('utf-8')` soup = BeautifulSoup(html, features='lxml')` sub_urls = soup.find_all("a", { "href": re.compile("content_cvpr_2018/html/(.)+CVPR_2018_paper.html$")})` k=len(sub_urls)` with open(filename,'w',encoding='utf-8') as f:` for i in range (k):` his=sub_urls[i]['href']` url= b_url + his` html2 = urlopen(url).read().decode('utf-8')` soup2 = BeautifulSoup(html2, features='lxml')` sub_urls2 = soup2.find_all("div",id="papertitle")` sub_urls3 = soup2.find_all("div",id="abstract")` sub_urls4 = soup2.find_all("a", { "href":re.compile("(.)+CVPR_2018_paper.pdf$")})` j=str(i)` f.write(j)` f.write('\n')` f.write("Title:"+sub_urls2[0].text.lstrip('\n'))` f.write('\n')` f.write("Abstract:"+sub_urls3[0].text.lstrip('\n'))` f.write('\n')` l=sub_urls4[0]['href'][6:-1]` link=b_url+l` f.write("Link:"+link)` f.write("\n\n\n")`
測試使用了977篇論文爬取結果做爲輸入數,命令行參數爲
-i D:\\date.txt -o result.txt -w 1 -m 3 -n 10
結果爲:
性能報告以下:
顯然耗時最大的函數爲Word_Fre()進行單詞斷定和詞組輸出,因此會比較耗時,能夠看出主要耗時在單詞斷定上,我將map改成unordered_map時間並無明顯提高。
設計了十個單元測試樣例,被說明測試的函數,構造測試數據見下表:
測試名 | 單元測試內容 | 測試模塊 | 結果 |
---|---|---|---|
UnitTestCharNum | 正常文本輸入,統計字符數量 | CharNum.cpp | 經過 |
UnitTestLineNum | 正常文本輸入,統計有效行數量 | LineNum.cpp | 經過 |
UnitTestWordNum | 正常文本輸入,統計單詞數量 | WordNum.cpp | 經過 |
specialfile | Abstract : 行爲空的文本,有效行數量 | LIneNum.cpp | 經過 |
emptya | 傳入一個空文件,輸出爲0 | CharNUm.cpp LIneNum.cpp WordNum.cpp | 經過 |
twowordnum | 兩個單詞的詞組數量 | Word_Fre.cpp | 經過 |
emptyinputfile | 沒有-i參數的傳入,錯誤報告 | main.cpp | 經過 |
topntest | top3輸出 | Word_Fre.cpp | 經過 |
weightwordfre | 加入權重的單詞頻率輸出 | Word_Fre.cpp | 經過 |
運行結果以下:
部分代碼展現以下:
namespace UnitTestCharNum { TEST_CLASS(UnitTest1) { public: TEST_METHOD(TestMethod1) { char filename[30] = "D:\\demo.txt"; int count = CharNum(filename); Assert::IsTrue(count == 74); // TODO: 在此輸入測試代碼 } }; } namespace UnitTestLineNum { TEST_CLASS(UnitTest1) { public: TEST_METHOD(TestMethod1) { char filename[30] = "D:\\demo.txt"; int count = LineNum(filename); Assert::IsTrue(count == 2); // TODO: 在此輸入測試代碼 } }; } namespace UnitTestWordNum { TEST_CLASS(UnitTest1) { public: TEST_METHOD(TestMethod1) { char filename[30] = "D:\\demo.txt"; int count = WordNum(filename)-2; Assert::IsTrue(count == 9); // TODO: 在此輸入測試代碼 } }; } namespace emptya { TEST_CLASS(UnitTest1) { public: TEST_METHOD(TestMethod1) { char filename[30] = "D:\\demo2.txt"; int count = LineNum(filename); Assert::IsTrue(count == 1); // TODO: 在此輸入測試代碼 } }; }
主要問題是爬蟲和詞組的判斷
一開始嘗試詞組打算用我的項目的那個代碼,只不過是多循環幾回,後來發現單純的在原來word的基礎上增長長度,這樣判斷詞組會有之後,即不能回讀。
算是圓滿地解決了,經過string數組暫時存放單詞,這樣就能夠在光標移到後面,也能夠回讀前面的單詞。
有,好比軟工實踐仍是要趁早作,就像前面說的,deadline並非萬能的。
還有學習新知識必定要耐心,如何從浩瀚的網絡海洋中學到你想要的,這是一門人生的必修課
個人隊友,高端大氣上檔次,低調奢華有內涵。
第N周 | 新增代碼(行) | 累計代碼(行) | 本週學習耗時(小時) | 累計學習耗時(小時) | 重要成長 |
1 | 300 | 300 | 15 | 15 | 熟悉了C++語言,瞭解了單元測試,代碼覆蓋率和性能分析 |
2 | 0 | 300 | 8 | 23 | |
3 | 300 | 600 | 14 | 37 | 爬蟲,代碼能力更上一步 |
... |