Python编写网页爬虫爬取oj上的代码信息

OJ升级,代码可能会丢失. 所以要事先备份. 一开始傻傻的复制粘贴, 后来实在不能忍, 得益于大潇的启发和聪神的原始代码, 网页爬虫走起!

已经有段时间没看Python, 这次网页爬虫的原始代码是 python2.7版本, 试了一下修改到3.0版本, 要做很多包的更替,感觉比较烦,所以索性就在这个2.7版本上完善了.

首先观赏一下原始代码,我给加了一些注释:

# -*- coding: cp936 -*-

import urllib2
import urllib
import re
import thread
import time
import cookielib

cookie_support = urllib2.HTTPCookieProcessor(cookielib.CookieJar())
opener = urllib2.build_opener(cookie_support,urllib2.HTTPHandler)
urllib2.install_opener(opener)

# 下面是正则表达式部分,意在过滤爬取页面的标签信息
class Tool:
    A = re.compile(" \;")                           #A-J对标签进行匹配
    B = re.compile("\<BR\>")
    C = re.compile("<\;")
    D = re.compile(">\;")
    E = re.compile(""\;")
    F = re.compile("&")
    G = re.compile("Times\ New\ Roman\"\>")
    H = re.compile("\</font\>")
    I = re.compile("‘")
    J = re.compile(r‘语言.*?face=‘)
    def replace_char(self,x):                      #将标签内容替换成目标内容
        x=self.A.sub(" ",x)
        x=self.B.sub("\n\t",x)
        x=self.C.sub("<",x)
        x=self.D.sub(">",x)
        x=self.E.sub("\"",x)
        x=self.F.sub("&",x)
        x=self.G.sub("",x)
        x=self.H.sub("",x)
        x=self.I.sub("\‘",x)
        x=self.J.sub("",x)
        return x

class HTML_Model:
    def __init__(self,u,p):
        self.userName = u                 #用户名和密码等登入信息
        self.passWord = p
        self.mytool = Tool()
        self.page = 1                      #从代码页的第一页开始爬
        self.postdata = urllib.urlencode({
            ‘userName‘:self.userName,
            ‘password‘:self.passWord
})
    def GetPage(self):
        myUrl = "http://acm.njupt.edu.cn/acmhome/login.do"

        #请求包括网址和登入表单
        req=urllib2.Request(
            url = myUrl,
            data = self.postdata
            )
        #此次相应为打开这个url
        myResponse = urllib2.urlopen(req)

        #读取页面
        myPage = myResponse.read()
        flag = True

        #当flag为true时 继续抓取下一页
        while flag:
            #下一页网址
            myUrl="http://acm.njupt.edu.cn/acmhome/showstatus.do?problemId=null&contestId=null&userName="+self.userName+"&result=1&language=&page="+str(self.page)
            #print(myUrl)
            myResponse = urllib2.urlopen(myUrl)
            #打开下一页的页面
            myPage = myResponse.read()

            #正则表达式搜索是否还有下一页,更新flag. 原理为在当前页查找, 如果当前页面有提交的代码,则含有类似"<a href="/acmhome/solutionCode.do?id=4af76cc2459a0dd30145eb3dd1671dc5" target="_blank">G++</a>" 这样的标签. 也就是说如果我的代码只有84页,那么则在第85页flag-false,不再访问86页
            st="\<a\ href\=.*?G\+\+"
            next = re.search(st,myPage)
            #print(st)
            print(next)
            if next:
                flag=True
                print("True")
            else:
                flag=False
                print("False")
            #print(myPage)
           #找到当前页面下所有题目代码的连接,放在myItem这个list中
            myItem = re.findall(r‘<a href=\"/acmhome/solutionCode\.do\?id\=.*?\"\ ‘,myPage,re.S)
            for item in myItem:
                #print(item)
 
               #对于每个题目代码连接,访问其所在页面
                url=‘http://acm.njupt.edu.cn/acmhome/solutionCode.do?id=‘+item[37:len(item)-2]
                #print(url)
                myResponse = urllib2.urlopen(url)
                myPage = myResponse.read()
                mytem = re.findall(r‘语言.*?</font>.*?Times New Roman\"\>.*?\</font\>‘,myPage,re.S)
                #print(mytem)
                sName = re.findall(r‘源代码--.*?</strong‘,myPage,re.S)
                #sName = sName[2:len(sName)]
                for sname in sName:
                    print(sname[2:len(sname)-8])
                    # sname中包含了题号信息
                    f = open(sname[2:len(sname)-8]+‘.txt‘,‘w+‘)
                    #通过前面的标签过滤函数,将过滤后的代码写在文件里
                    f.write(self.mytool.replace_char(mytem[0]))
                    f.close()
                    print(‘done!‘)
            self.page = self.page+1

print u‘plz input the name‘
u=raw_input()
print u‘plz input password‘
p=raw_input()
#u = "B08020129"
#p = *******"
myModel = HTML_Model(u,p)
myModel.GetPage()

现在这个代码有两个问题:

首先,在标签匹配的时候没有支持多行,也就是爬下来的代码中仍然包含跨度多行的标签, 纯代码仍然需要人工提取.

第二,因为代码页面并没有问题的题目信息,所以仅以题号作为文件名. 这样若果升级后的OJ题目顺序发生改变, 将无法将题目与代码进行对应.

针对第一个问题, 修正的方法比较简单:

在正则表达式匹配的时候, 将第二个参数位置加上re.DOTALL即可.

例如:

J = re.compile(r‘语言.*?face=‘,re.DOTALL)

对于第二个问题, 可以根据题号寻找题目的页面(而非此前代码的页面), 然后从题目页面中提取标题信息.

在题目页面中,我发现只有标题是用<strong><\strong> 标签修饰的,所以可以这样匹配

sName2=re.findall(r‘<strong>([^<]+)</strong>‘,myPage2,re.S)

另外文件命名的时候不可以有空格,所以还要滤除空格

sname2=sname2.replace(" ","")

即使这样,有时在创建文件时仍然会抛出异常, 但是重新执行一次可能就会不再出现问题.

下面是晚上后的代码, 修改的地方加粗了.

# -*- coding: cp936 -*-

import urllib2
import urllib
import re
import thread
import time
import cookielib

cookie_support = urllib2.HTTPCookieProcessor(cookielib.CookieJar())
opener = urllib2.build_opener(cookie_support,urllib2.HTTPHandler)
urllib2.install_opener(opener)

class Tool:
    A = re.compile(" \;")
    B = re.compile("\<BR\>")
    C = re.compile("<\;")
    D = re.compile(">\;")
    E = re.compile(""\;")
    F = re.compile("&")
    G = re.compile("\"Times\ New\ Roman\"\>")
    H = re.compile("\</font\>")
    I = re.compile("‘")
    J = re.compile(r‘语言.*?face=‘,re.DOTALL)
    def replace_char(self,x):
        x=self.A.sub(" ",x)
        x=self.B.sub("\n\t",x)
        x=self.C.sub("<",x)
        x=self.D.sub(">",x)
        x=self.E.sub("\"",x)
        x=self.F.sub("&",x)
        x=self.G.sub("",x)
        x=self.H.sub("",x)
        x=self.I.sub("\‘",x)
        x=self.J.sub("",x)
        return x

class HTML_Model:
    def __init__(self,u,p):
        self.userName = u
        self.passWord = p
        self.mytool = Tool()
        self.page = 81
        self.postdata = urllib.urlencode({
            ‘userName‘:self.userName,
            ‘password‘:self.passWord
})
    def GetPage(self):
        myUrl = "http://acm.njupt.edu.cn/acmhome/login.do"
        req=urllib2.Request(
            url = myUrl,
            data = self.postdata
            )
        myResponse = urllib2.urlopen(req)
        myPage = myResponse.read()
        flag = True
        while flag:
            myUrl="http://acm.njupt.edu.cn/acmhome/showstatus.do?problemId=null&contestId=null&userName="+self.userName+"&result=1&language=&page="+str(self.page)
            #print(myUrl)
            myResponse = urllib2.urlopen(myUrl)
            myPage = myResponse.read()
            st="\<a\ href\=.*?G\+\+"
            next = re.search(st,myPage)
            #print(st)
            print(next)
            if next:
                flag=True
                print("True")
            else:
                flag=False
                print("False")
            #print(myPage)
            myItem = re.findall(r‘<a href=\"/acmhome/solutionCode\.do\?id\=.*?\"\ ‘,myPage,re.S)
            for item in myItem:
                #print(item)
                url=‘http://acm.njupt.edu.cn/acmhome/solutionCode.do?id=‘+item[37:len(item)-2]
                #print(url)
                myResponse = urllib2.urlopen(url)
                myPage = myResponse.read()
                mytem = re.findall(r‘语言.*?</font>.*?Times New Roman\"\>.*?\</font\>‘,myPage,re.S)
                #print(mytem)
                sName = re.findall(r‘源代码--.*?</strong‘,myPage,re.S)
                #sName = sName[2:len(sName)]

                for sname in sName:
                    url2="http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id="+sname[8:len(sname)-8]
                    myResponse2=urllib2.urlopen(url2)
                    myPage2=myResponse2.read();

                    sName2=re.findall(r‘<strong>([^<]+)</strong>‘,myPage2,re.S)
                    sname2=sName2[0]
                    sname2=sname2.replace(" ","")
                   # print(sName)
                    print(sname[8:len(sname)-8]+‘.‘+sname2[0:len(sname2)])
                    f = open(sname[8:len(sname)-8]+‘.‘+sname2[0:len(sname2)]+‘.txt‘,‘w+‘)
                    f.write(self.mytool.replace_char(mytem[0]))
                    f.close()
                    print(‘done!‘)

            print(self.page)
            self.page = self.page+1

#print u‘plz input the name‘
#u=raw_input()
#print u‘plz input password‘
#p=raw_input()
u = "LTianchao"
p = "******"
myModel = HTML_Model(u,p)
myModel.GetPage()

关于Python的网页爬取问题,这只是一个很简单的demo, 下面还需要深入学习.(如果有时间的话)

Python编写网页爬虫爬取oj上的代码信息

时间: 2024-08-02 10:57:04

Python编写网页爬虫爬取oj上的代码信息的相关文章

爬虫 爬取天猫商品的封面信息

# 爬取搜索字段的封面信息 ''' q : 搜索的类型 可以识别中文 天猫控制登录字段: sort: 排序 s:起始第几个商品 问题1: 把s删除以后,虽说可以跳过登陆,但是只能访问第一页了,何解? 解决: 多次点击页面后发现,淘宝测试不完全,在点击跳转页面后,将其的url后的参数只保留 q totalPage jumpto 三个字段后,就可以通过修改jumpto字段的值 来跳转到其他的页面 问题2: 解决登陆问题后,发现无法提前知道totalpage的总页数 解决:只要页面有显示,那我们就能拿

用Python实现一个爬虫爬取ZINC网站进行生物信息学数据分析

最近接到实验室的导师交给我的一个任务,就是他们手头有很多smile表达式,格式类似这种:C(=C(c1ccccc1)c1ccccc1)c1ccccc1(这是生物信息学中表达小分子结构的一种常用表达式),他们需要对每个smile表达式在ZINC网站(生物信息学数据网站)上进行搜索,然后找到对应的ZINC号.小分子供应商.构象预测等信息.基本步骤如下: 点击查找之后网页就会跳转到详细信息,我们需要获取它的ZINC号.小分子供应商.构象预测.CAS号等信息,如下: 这一套流程要是靠人工手动完成的话有点

python 使用scrapy框架爬取一个图书网站的信息

1.新建项目 scrapy start_project book_project 2.编写items类 3.编写spider类 # -*- coding: utf-8 -*- import scrapy from book_project.items import BookItem class BookInfoSpider(scrapy.Spider): name = "bookinfo"#定义爬虫的名字 allowed_domains = ["allitebooks.com

Python的scrapy之爬取链家网房价信息并保存到本地

因为有在北京租房的打算,于是上网浏览了一下链家网站的房价,想将他们爬取下来,并保存到本地. 先看链家网的源码..房价信息 都保存在 ul 下的li 里面 ? 爬虫结构: ? 其中封装了一个数据库处理模块,还有一个user-agent池.. 先看mylianjia.py # -*- coding: utf-8 -*- import scrapy from ..items import LianjiaItem from scrapy.http import Request from parsel i

NodeJS 爬虫爬取LOL英雄联盟的英雄信息,superagent+cheerio+async

1.模块使用 (1)superagent:Nodejs中的http请求库(每个语言都有无数个,java的okhttp,ios的afnetworking) (2)cheerio:Nodejs中的html解析库(每个语言基本都有..) (3)async:Nodejs中的同/异步并发函数执行库(这个非常牛,其他语言同类型的不多) 2.爬取内容 多玩的英雄联盟英雄页面,通过解析页面内每个英雄的URL,然后并发请求英雄的详细数据,提取需要的数据得到结果 http://lol.duowan.com/hero

python设置代理IP来爬取拉勾网上的职位信息,

import requests import json import time position = input('输入你要查询的职位:') url = 'https://www.lagou.com/jobs/positionAjax.json?city=%E6%9D%AD%E5%B7%9E&needAddtionalResult=false' headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/5

python beautifulsoup bs4爬虫 爬取糗事百科

声明:仅用于学习语法,请勿用于非法用途 import urllib.request import re from bs4 import BeautifulSoup # -*- coding:utf-8 -*- url = 'http://www.qiushibaike.com/hot/' user_agent='Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)' headers={'User-Agent':user_agent} request = u

python获取网页精准爬取数据

import reimport urllib.requeststring='<div class="name">(.*?)</div>'huo=urllib.request.urlopen("https://read.douban.com/provider/all").read()huo=huo.decode("utf-8")huo1=re.compile(string).findall(str(huo))hom=open

使用python爬取MedSci上的影响因子排名靠前的文献

使用python爬取medsci上的期刊信息,通过设定条件,然后获取相应的期刊的的影响因子排名,期刊名称,英文全称和影响因子.主要过程如下: 首先,通过分析网站http://www.medsci.cn/sci的交互过程.可以使用谷歌或火狐浏览器的“审查元素-->Network”,然后就可以看到操作页面就可以看到网站的交互信息.当在网页上点击“我要查询”时,网页会发送一个POST消息给服务器,然后,服务器返回查询结果 然后,将查询到的结果使用正则表达式提取出需要的数据. 最后将提取出的数据输出到文