上海交通大学ACM Online Judge 评测状态的爬取

博主刚刚学习Python爬虫没多久,大概对requests库、BeautifulSoup库有所了解,准备找个网站练练手,于是就选了OJ。

首先是使用requests库获得网页的html文本,这都是有各种框架了,就不再赘述。

def getHTML(url):
	try:
		head={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}
		r = requests.get(url,headers=head)
		r.raise_for_status()
		r.encoding = r.apparent_encoding
		return r.text
	except:
		return ''
然后就是使用BeautifulSoup解析html网页,接着需要提取我们需要的信息,网页显示如下:


然后查看网页源代码,可以发现所有这些状态都包含在tbody标签里,而每条状态都是包含在tr标签里,

 <tbody>
          <tr>
        <td><a href="/OnlineJudge/status?owner=&problem=&language=&verdict=&top=445095">445095</a></td>
        <td>516030910365 吴薄鸿</td>
        <td>
          <a href="/OnlineJudge/problem/4012">4012</a>
                  </td>
        <td>
                      <span class="recordMemoryLimitExceeded">超过内存限制</span>
                  </td>
                <td>0ms</td>
        <td>0kb</td>
        <td>C++</td>
        <td>2017-11-02 13:04:05</td>
      </tr>
          <tr>
        <td><a href="/OnlineJudge/status?owner=&problem=&language=&verdict=&top=445094">445094</a></td>
        <td>517021911076 李晓妍</td>
        <td>
          <a href="/OnlineJudge/problem/4058">4058</a>
                  </td>
        <td>
                      <span class="recordAccepted">正确</span>
                  </td>
                <td>4ms</td>
        <td>5316kb</td>
        <td>C++</td>
        <td>2017-11-02 13:03:07</td>
      </tr>
所以可以使用一个列表来将这些状态存储,同时由于提取是从上往下提取,所以列表前面的是最新的,后面是较早的,为了输出方便,可以将列表倒序以下。
def getList(url):
	html=getHTML(url)
	soup=BeautifulSoup(html,'html.parser')
	urlList=[]
	for obj in soup.tbody.findAll('tr'):
		urlList.append(obj)
	urlList.reverse()
	return urlList
再然后就是遍历列表中的每一个对象,再对每一个对象进行一些处理,写入文件中。

def writeList(urlList,startIndex=0):
	f=open('scrapy.txt','a')
	t=time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
	f.write('Run Time: '+t+'\n')
	if startIndex==len(urlList)-1:
		return 0
	for i in range(startIndex+1,len(urlList)):
		for obj in urlList[i]:
			if obj=='\n':
				pass
			elif obj.string!=None:
				f.write(obj.string+'\t')
			elif obj.a!=None:
				f.write(obj.a.string+'\t')
			elif obj.span!=None:
				f.write(obj.span.string+'\t')
		f.write('\n')
	f.close()
我希望每当页面上有新的状态出现时,可以继续写入文件,所以每隔一段时间爬取一下网页,然后从刚爬取的newlist中选取oldlist中没有的写入文件即可。主要方法是返回oldlist最后一个元素在newlist中的位置,然后从那个位置开始写入。

def getLastedNo(urlList):
	return urlList[-1].td.string

def getFirstIndex(urlList,no):
	for i in range(len(urlList)):
		if urlList[i].td.string==no:
			return i

最后就是将这些模块整合起来,每隔一段时间爬取一次,将新的写入文件即可。

url='https://acm.sjtu.edu.cn/OnlineJudge/status'
oldList=getList(url)
f=open('scrapy.txt','a')
f.write('=================================\n')
f.close()
writeList(oldList,0)
i=0
print (i)
while True:
	time.sleep(200)
	newList=getList(url)
	start=getFirstIndex(newList,getLastedNo(oldList))
	writeList(newList,start)
	oldList=newList
	i+=1
	print (i)
爬取结果如下:



最后,这个程序还有很多Bug,还需要慢慢改进。



                
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值