python刷题软件_教你用python写:HDU刷题神器
聲明:本文以學習為目的,請不要影響他人正常判題
HDU刷題神器,早已被前輩們做出來了,不過沒有見過用python寫的。大一的時候見識了學長寫這個,當時還是一臉懵逼,只知道這玩意兒好屌…。時隔一年,決定自己實現這個功能。
刷到第13名,AC率不高,因為,搜索引擎搜到的結果,往后就很難找到正確的代碼了
首先對辛苦刷題的acmer和hdu的管理員道歉,各位,抱歉。
介紹整體思路:
整體用多線程:線程執行從爬代碼到提交的全部過程
分層次:對搜索引擎搜索的結果,進行劃分,分層爬取
局部思路:
爬取搜索引擎得到的與題目相關的url,得到url_list
爬取url_list中的url,扒到代碼就提交
檢查提交結果,WA之后繼續爬取url_list中的代碼
循環,直到列表為空或者AC
相關模塊:
threadpool線程池,分配線程任務,多線程并發提交代碼
用requests模塊發送請求
正則爬取url和代碼
Sqlite存放AC代碼(打表啊,再申請個賬號從數據庫中提交代碼100%AC)
1)采用線程池實現多線程,注意控制最大并發數量
搜索引擎使用CSDN的搜索,因為我們爬取的代碼全都來自CSDN的博客,可以看一下其他論壇,博客的代碼:
(右鍵,在新標簽頁中打開查看高清圖片)
(右鍵,在新標簽頁中打開查看高清圖片)
哦,這實在太不友好了,而CSDN博客的代碼就好很多了(盡管很友好了,class和name有些先后順序不一樣,也會添亂)
所以,我們決定扒CSDN博客的代碼。
搜索引擎的選擇,CSDN(部分搜索結果是百度提供的)
其實,第一想到的是百度的,然而。。。
加密了,增大了我們的工作量,所以,就直接用CSDN的(也有百度的結果)
在CSDN搜索結果的最下方,我們可以看到上圖中有14W結果(好唬人啊),其實事情是這樣的:
這是一個搜索hdu 1000的url,我們注意到用的get()方法傳數據,發現只有p=?,試一下就知道,這個是頁碼。如果頁碼改為200呢?
100?
開玩笑啊,14W結果呢?最后我們得出結論:搜索結果只有76頁,而且越往后,得到我們想要代碼的可能性就越小,所以我只爬到20頁就結束程序
關于線程池的部分,在大牛博客說的很清楚,通過threadpool模塊的源碼,可以理解的很清楚
注意線程池添加任務,給任務傳遞多參數,需要查看源碼,理解參數傳遞的過程,
1 #coding :utf-8
2 #@Time : 2017/8/7 11:24
3 #@Author : Yong-life
4 #@File : crawling_hdu.py
5
6 importrequests7 importre8 from headers_cookies import *
9 importthreadpool10 from searching_code importsubmit_code_from_url11
12 '''
13 我要AK HDU14
15 需要安裝threadpool,requests,pywin32模塊16 先打開chrome瀏覽器登錄hdu(cookies是從chrome拿的,剛登陸后可能因為cookie的問題程序拋出ValueError的異常,多啟動幾次就好了)17 '''
18
19
20 defsearch_pid():21 problem_list =[]22 '''共52頁題目'''
23 page_number = 52 + 1
24 for i inrange(page_number):25 '''請求url'''
26 url = 'http://acm.hdu.edu.cn/listproblem.php?vol=' +str(i)27 response = requests.get(url, headers=get_headers(), cookies=get_cookie_from_chrome())28 '''抓取題目信息'''
29 patternPidList = r'>'
30 problems = re.search(patternPidList, response.text).group(1).split(';')31 for problem inproblems:32 try:33 pid = int(problem[4:8])34 status = int(problem[9])35 problem_list.append((pid, status))36 exceptValueError:37 '''ValueError'''
38 print(type(pid), pid, type(status), status)39
40 returnproblem_list41
42
43 defstart_crawling():44 pid_list =[]45 '''最大并發數量,超過10就很影響別人,相當于同時有5個人在提交代碼,提交一次判斷完成后才會繼續提交其他代碼'''
46 THREAD_NUMBER = 5
47 '''從搜索到的第crawl_level_begin頁繼續開始扒代碼'''
48 crawl_level_begin = 1
49 '''分段式扒代碼'''
50 crawl_level = 4
51 END_MARK =True52 whileEND_MARK:53 print("正在爬取題目信息……")54 for problem insearch_pid():55 pid, status =problem56 if status != 5:57 '''多參數構造'''
58 pid_list.append(([pid, crawl_level_begin, crawl_level], None)) #必須封裝為元組,否則會給參數再封裝一層列表,也可以改目標函數
59 if len(pid_list) ==THREAD_NUMBER:60 '''定義線程池大小'''
61 task_pool =threadpool.ThreadPool(THREAD_NUMBER)62 '''任務列表'''
63 request_task =[]64 '''構造任務列表'''
65 request_task =threadpool.makeRequests(submit_code_from_url, pid_list)66 '''將每個任務放到線程池中,等待線程池中線程各自讀取任務'''
67 [task_pool.putRequest(req) for req inrequest_task]68 '''等待所有任務處理完成,則返回,如果沒有處理完,則一直阻塞'''
69 task_pool.wait()70
71 pid_list =[]72 '''判斷是否全對,全對結束'''
73 END_MARK =False74 print('正在搜索AC情況,,,')75 for status in search_pid()[1]:76 if status != 5:77 END_MARK =True78 print('未AK...')79 '''增加搜索范圍'''
80 crawl_level_begin =crawl_level81 crawl_level += 4
82 print('增大搜索范圍繼續搜索...')83 print('當前搜索范圍:', crawl_level_begin, crawl_level)84 break
85
86 '''CSDN搜索最搜索到30頁數據,而且部分是百度提供的結果'''
87 if crawl_level > 30:88 break
89
90 print('AK!')91
92
93 if __name__ == '__main__':94 start_crawling()
2)線程開始跑了:分布式思想,分塊,分層,完成AK任務
爬取crawl_level_begin-crawl_level頁搜索結果的url
按照url_list爬取代碼
提交代碼
每輪爬完6000+題后,判斷是否AK,AK則結束程序,否則增加crawl_level繼續查找代碼提交
經過剪枝優化,代碼更快了
1 #coding :utf-8
2 #@Time : 2017/8/7 15:06
3 #@Author : Yong-life
4 #@File : searching_code.py
5
6 from urllib importrequest7 importurllib8 from headers_cookies importget_headers9 importre10 importsqlite311 from sqlite_hdu importSql12 from submit_codes import *
13 importthreading14 from submit_codes importSubmitCode15 importsys16
17
18 defsubmit_code_from_url(pid, crawl_level_begin, crawl_level):19 '''爬取url_list,提交代碼'''
20 url_list =code_url_list(str(pid), crawl_level_begin, crawl_level)21 for url inurl_list:22 '''僅爬取博客鏈接'''
23 if url[7:11] != 'blog': #刪選url
24 continue
25 code =crawling_code(pid, url)26 if code == '':27 '''未查找到代碼'''
28 continue
29 submit =SubmitCode(pid, code)30 ifsubmit.submit_manager():31 '''AC,保存代碼'''
32 sql_save_code =Sql()33 if sql_save_code.query_pid(pid) isNone:34 sql_save_code.insert_msg(pid, 5, code)35 else:36 sql_save_code.update_problem_code(pid, code)37 sql_save_code.sql_close()38 return
39
40 print("爬取代碼完畢,任務結束:" + str(pid) + "提交尚未成功!")41 return
42
43
44 def code_url_list(problem_msg, crawl_level_begin, crawl_level): #題號和其他信息
45 '''爬取題目鏈接'''
46 url_list =[]47 '''頁碼,根據爬蟲等級,擴大搜索范圍'''
48 page_number =crawl_level_begin49 '''最大頁碼'''
50 MAX_PAGE =crawl_level51 while page_number
&q
<<>"&&+'??
&pid&user&lang&status
總結
以上是生活随笔為你收集整理的python刷题软件_教你用python写:HDU刷题神器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: web3j批量转账
- 下一篇: 韩创科技php面试题_2018年韩创科技