python爬虫学习(11) —— 也写个AC自动机
0. 写在前面
本文记录了一个AC自动机的诞生!
之前看过有人用C++写过AC自动机,也有用C#写的,还有一个用nodejs写的。。
感觉他们的代码过于冗长,而且AC率也不是很理想。
刚好在回宿舍的路上和学弟聊起这个事
随意想了想思路,觉得还是蛮简单的,就顺手写了一个,效果,还可以接受。
先上个图吧:
最后应该还可以继续刷,如果修改代码或者再添加以下其他搜索引擎可以AC更多题,
不过我有意控制在3000这个AC量,也有意跟在五虎上将之后。
1. 爬虫思路
思路其实非常清晰:
- 模拟登录HDU
- 针对某一道题目
- 搜索AC代码
- 通过正则表达式进行代码的提取
- 通过htmlparser进行代码的处理
- 提交
- 若AC,返回2
- 否则,继续提交代码(这里最多只提交10份代码)
- 10次提交后还未AC,放弃此题
- 搜索AC代码
2. 简单粗暴的代码
#coding='utf-8'
import requests, re, os, HTMLParser, time, getpass
host_url = 'http://acm.hdu.edu.cn'
post_url = 'http://acm.hdu.edu.cn/userloginex.php?action=login'
sub_url = 'http://acm.hdu.edu.cn/submit.php?action=submit'
csdn_url = 'http://so.csdn.net/so/search/s.do'
head = { 'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36' }
html_parser = HTMLParser.HTMLParser()
s = requests.session()
def login(usr,psw):
s.get(host_url);
data = {'username':usr,'userpass':psw,'login':'Sign In'}
r = s.post(post_url,data=data)
def check_lan(lan):
if 'java' in lan:
return '5'
return '0'
def parser_code(code):
return html_parser.unescape(code).encode('utf-8')
def is_ac(pid,usr):
tmp = requests.get('http://acm.hdu.edu.cn/userstatus.php?user='+usr).text
accept = re.search('List of solved problems</font></h3>.*?<p align=left><script language=javascript>(.*?)</script><br></p>',tmp,re.S)
if pid in accept.group(1):
print '%s was solved' %pid
return True
else:
return False
def search_csdn(PID,usr):
get_data = { 'q':'HDU ' + PID, 't':'blog', 'o':'', 's':'', 'l':'null' }
search_html = requests.get(csdn_url,params=get_data).text
linklist = re.findall('<dd class="search-link"><a href="(.*?)" target="_blank">',search_html,re.S)
for l in linklist:
print l
tm_html = requests.get(l,headers=head).text;
title = re.search('<title>(.*?)</title>',tm_html,re.S).group(1).lower()
if PID not in title:
continue
if 'hdu' not in title:
continue
tmp = re.search('name="code" class="(.*?)">(.*?)</pre>',tm_html,re.S)
if tmp == None:
print 'code not find'
continue
LAN = check_lan(tmp.group(1))
CODE = parser_code(tmp.group(2))
if r'include' in CODE:
pass
elif r'import java' in CODE:
pass
else:
continue
print PID, LAN
print '--------------'
submit_data = { 'check':'0', 'problemid':PID, 'language':LAN, 'usercode':CODE }
s.post(sub_url,headers=head,data=submit_data)
time.sleep(5)
if is_ac(PID,usr):
break
if __name__ == '__main__':
usr = raw_input('input your username:')
psw = getpass.getpass('input your password:')
login(usr,psw)
pro_cnt = 1000
while pro_cnt <= 5679:
PID = str(pro_cnt)
if is_ac(PID,usr):
pro_cnt += 1
continue
search_csdn(PID,usr)
pro_cnt += 1
代码不长,仅仅只有78行,是的,就是这样!
3. TDDO
目前没有打算完善这篇博客,也不推荐去研究这个东西,推荐的是去学习真正的算法,哈哈!
很久很久以前自己写过的AC自动机,,,,贴一发:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define clr( a, b ) memset( a, b, sizeof(a) )
const int SIGMA_SIZE = 26;
const int NODE_SIZE = 500000 + 10;
struct ac_automaton{
int ch[ NODE_SIZE ][ SIGMA_SIZE ];
int f[ NODE_SIZE ], val[ NODE_SIZE ], last[ NODE_SIZE ];
int sz;
void init(){
sz = 1;
clr( ch[0], 0 ), clr( val, 0 );
}
void insert( char *s ){
int u = 0, i = 0;
for( ; s[i]; ++i ){
int c = s[i] - 'a';
if( !ch[u][c] ){
clr( ch[sz], 0 );
val[sz] = 0;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u]++;
}
void getfail(){
queue<int> q;
f[0] = 0;
for( int c = 0; c < SIGMA_SIZE; ++c ){
int u = ch[0][c];
if( u ) f[u] = 0, q.push(u), last[u] = 0;
}
while( !q.empty() ){
int r = q.front(); q.pop();
for( int c = 0; c < SIGMA_SIZE; ++c ){
int u = ch[r][c];
if( !u ){
ch[r][c] = ch[ f[r] ][c];
continue;
}
q.push( u );
int v = f[r];
while( v && !ch[v][c] ) v = f[v];
f[u] = ch[v][c];
last[u] = val[ f[u] ] ? f[u] : last[ f[u] ];
}
}
}
int work( char* s ){
int res = 0;
int u = 0, i = 0, e;
for( ; s[i]; ++i ){
int c = s[i] - 'a';
u = ch[u][c];
e = u;
while( val[e] ){
res += val[e];
val[e] = 0;
e = last[e];
}
}
return res;
}
}ac;
python爬虫学习(11) —— 也写个AC自动机的更多相关文章
- python爬虫学习 —— 总目录
开篇 作为一个C党,接触python之后学习了爬虫. 和AC算法题的快感类似,从网络上爬取各种数据也很有意思. 准备写一系列文章,整理一下学习历程,也给后来者提供一点便利. 我是目录 听说你叫爬虫 - ...
- python爬虫学习(1) —— 从urllib说起
0. 前言 如果你从来没有接触过爬虫,刚开始的时候可能会有些许吃力 因为我不会从头到尾把所有知识点都说一遍,很多文章主要是记录我自己写的一些爬虫 所以建议先学习一下cuiqingcai大神的 Pyth ...
- Python爬虫学习:二、爬虫的初步尝试
我使用的编辑器是IDLE,版本为Python2.7.11,Windows平台. 本文是博主原创随笔,转载时请注明出处Maple2cat|Python爬虫学习:二.爬虫的初步尝试 1.尝试抓取指定网页 ...
- 《Python爬虫学习系列教程》学习笔记
http://cuiqingcai.com/1052.html 大家好哈,我呢最近在学习Python爬虫,感觉非常有意思,真的让生活可以方便很多.学习过程中我把一些学习的笔记总结下来,还记录了一些自己 ...
- python爬虫学习笔记(一)——环境配置(windows系统)
在进行python爬虫学习前,需要进行如下准备工作: python3+pip官方配置 1.Anaconda(推荐,包括python和相关库) [推荐地址:清华镜像] https://mirrors ...
- [转]《Python爬虫学习系列教程》
<Python爬虫学习系列教程>学习笔记 http://cuiqingcai.com/1052.html 大家好哈,我呢最近在学习Python爬虫,感觉非常有意思,真的让生活可以方便很多. ...
- Python爬虫学习02--pyinstaller
Python爬虫学习02--打包exe可执行程序 1.上一次做了一个爬虫爬取电子书的Python程序,然后发现可以通过pyinstaller进行打包成exe可执行程序.发现非常简单好用 2.这是上次写 ...
- Python爬虫学习第一记 (翻译小助手)
1 # Python爬虫学习第一记 8.24 (代码有点小,请放大看吧) 2 3 #实现有道翻译,模块一: $fanyi.py 4 5 import urllib.request 6 import u ...
- Python爬虫学习:三、爬虫的基本操作流程
本文是博主原创随笔,转载时请注明出处Maple2cat|Python爬虫学习:三.爬虫的基本操作与流程 一般我们使用Python爬虫都是希望实现一套完整的功能,如下: 1.爬虫目标数据.信息: 2.将 ...
随机推荐
- 前端MVVM框架设计及实现
最近抽出点时间想弄个dom模块化的模板引擎,不过现在这种都是MVVM自带的,索性就想自己造轮子写一个简单的MVVM框架了 借鉴的自然还是从正美的Avalon开始了,我2013年写过一个关于MVC MV ...
- 前端学HTTP之报文起始行
前面的话 如果说HTTP是因特网的信使,那么HTTP报文就是它用来搬东西的包裹了.HTTP报文是在HTTP应用程序之间发送的简单的格式化数据块,每条报文都包含一条来自客户端的请求,或者一条来自服务器的 ...
- Task三个列子的分享
这次要分享的是C#Task任务的几个列子,感觉最实用的是封装的分页任务执行方法,这个方法步奏也是目前在我工作中执行多任务常用的,不知道各位也有这用的情况,那么开始吧. 1.顺序任务执行 //顺序任务执 ...
- C语言用分别用递归和循环求数字的阶乘的方法
以下代码均为 自己 实现,嘻嘻! 参考文章:http://blog.csdn.net/talk_8/article/details/46289683 循环法 int CalFactorial(int ...
- ASP.NET Core 中文文档 第四章 MVC(3.3)布局视图
原文:Layout 作者:Steve Smith 翻译:娄宇(Lyrics) 校对:孟帅洋(书缘) 视图(View)经常共享视觉元素和编程元素.在本篇文章中,你将学习如何在你的 ASP.NET 应用程 ...
- iOS UINavigationController(内容根据iOS编程编写)
我们知道 UITabBarController 对象,可以通过使用该对象,用户可以切换不同的屏幕.当要切换的各个屏幕之间没有相互依存关系的时候,该对象可以很好的完成任务.但是当多个屏幕互有关系的时候, ...
- LeetCode Online Judge 1. Two Sum
刷个题,击败0.17%... Given an array of integers, return indices of the two numbers such that they add up t ...
- Mac制作U盘系统(OS X El Capitan)教程
前言部分 重装过Mac OS X系统的人应该都深有体会,通过自带的重新安装 Mac OS X功能恢复系统(开机时按Command+R) 要耗费10几个小时才能完成(请求苹果国外服务器),但如果通过U盘 ...
- git push不用重复输入用户名和密码(解决方案)
每次git push都要输入用户名和密码,有点麻烦,就上网搜了下解决方案. 网上的解决方案有的讲得不清晰,逐个试了后,总结下两种有效的解决方案. 方案一: 1.在计算机安装盘(即一般为C盘)下找到 ...
- angular的$filter服务
首先,介绍下$filter服务: 1.$filter是用来进行数据格式化的专用服务: 2.AngularJS内置了currency.date.filter.json.limitTo.lowercase ...