一:爬取人民教育出版社的课件
1.浏览器的配置
下面这个代码我是引用了网友的代码,这个浏览器的模拟我亲自试过,挺好用的。使用过程未出现错误。
def get_agent():
'''
模拟header的user-agent字段,
返回一个随机的user-agent字典类型的键值对
'''
agents = ['Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv,2.0.1) Gecko/20100101 Firefox/4.0.1',
'Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)']
fakeheader = {}
fakeheader['User-agent'] = agents[random.randint(0, len(agents))]
return fakeheader
浏览器的模拟很重要,对爬取数据能否成功起着很重要的角色。
模拟效果不好的话,只能爬取一小段数据,跟原来的网址代码差别很大
下面这个图是我没有使用模拟浏览器时所爬取的代码,会发现很多数据都没有爬取下来,比原来的网页的代码少了特别多。
2.代理IP地址
代理的IP 地址由于是网上找的免费的,很多ip都是不稳定的,直接会提示一方的电脑的不积极回应。这样会使程序直接报错。
所以大型的爬取都需要成本,有一些是付费的代理IP地址,这些相对比较稳定。
def get_proxy():
'''
简单模拟代理池
返回一个字典类型的键值对,
'''
proxy = ['http//117.68.192.78:18118','http//117.69.193.48:18118']
fakepxs = {}
fakepxs['http'] = proxy[random.randint(0, len(proxy))]
return fakepxs
二:文件夹的创建
path1='D:/教育数据包/'+variate[1]
path2=path1+'/'+variate[2]
path3=path2+'/'+variate[3]
path4=path3+'/'+variate[4]
if(not(os.path.exists(path1))): #创建文件夹。
os.mkdir(path1)
if(not(os.path.exists(path2))):
os.mkdir(path2)
if(not(os.path.exists(path3))):
os.mkdir(path3)
if(not(os.path.exists(path4))):
os.mkdir(path4)
if(variate[6]):
path5=path4+'/'+variate[5]+'.ppt'
Path是要建立的文件位置及文件名具体如下:
path='D:/数学'
if(not(os.path.exists(path))):
os.mkdir(path)
这个代码的意思是在D盘中建立一个名称为数学的文件夹。
三 :爬虫时对数据的存放规律化
爬取网页是对网页的存放结构去爬取下来,对自己的数据存放也规律化
对网页的年级,科目都进行爬取,保存进数据库中。
四 :将文件保存进数据库
将文件保存数据库,都要现将文件变为字节类的数据。
import base64
with open("D:/计科5181/xinwen.zip", "rb") as f:
zips=base64.b64encode(f.read()) #将文件转换为字节。
print(len(zips))
f.close()
将数据库的数据保存进文件中
path5=path4+'/'+variate[5]+'.ppt' #文件的位置
ppt=base64.b64decode(variate[6]) #将数据保存进文件中
file=open(path5,'wb')
file.write(ppt)
file.close()
五. 爬取文件的方法:
方法一:
import urllib.request
url="http://shouji.360tpcdn.com/180822/aa171e9134dfa23c1d22a182ecf6d50c/com.ss.android.article.video_268.apk"
downPath='..\\apks\s.apk' #本地的文件保存位置。
urllib.request.urlretrieve(url,downPath)
方法二:
import requests
d = requests.get(url)
with open('D:/计科5181/xinwen.swf','wb')as f:
f.write(d.content)
方法三:
import requests
d = requests.get(url, timeout=30,headers=get_agent())
with open('D:/计科5181/xinwen.swf','wb')as f:
for chunk in d.iter_content(chunk_size=100): #chunk_size 是下载时的字节量
f.write(chunk)
f.close()
下载文件时别忘了要有浏览器的模拟,没有浏览器会爬取不了。大文件下载时要使用方法三,分字节的下载,会更加稳定,不会造成数据的丢失。
六:文件保存文件顺序
七:程序的流程图
八、 完整的代码
import re,os,sys
import sqlite3
import time
import urllib.error
import base64
import requests
from lxml import etree
import matplotlib.pyplot as plt
import matplotlib.image as mping
import bs4
import random
htmls=[]
conn=sqlite3.connect('People_education.db')
c=conn.cursor()
try:
c.execute('''CREATE TABLE Education(id int,level1 text,level2 text,level3 text,level4 text,name text,
ppt LONGBOLB,zips LONGBLOB,swf LONGBLOB,rar LONGBLOB)''')
print("表-Students创建成功!\n")
except:
print("表-Students创建成功!")
c.close()
conn.close()
def get_agent():
'''
模拟header的user-agent字段,
返回一个随机的user-agent字典类型的键值对
'''
agents = ['Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv,2.0.1) Gecko/20100101 Firefox/4.0.1',
'Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)']
fakeheader = {}
fakeheader['User-agent'] = agents[random.randint(0, len(agents))]
return fakeheader
def get_proxy():
'''
简答模拟代理池
返回一个字典类型的键值对,
'''
proxy = ['http//117.68.192.78:18118']
fakepxs = {}
fakepxs['http'] = proxy[random.randint(0, len(proxy))]
return fakepxs
#,proxies=get_proxy()
# 注意看新的请求函数:
def get_html(url):
try:
r = requests.get(url,timeout=10,headers=get_agent())#timeout=10十秒钟的时间爬取。headers=get_agent()添加浏览器的模拟
pat1 = '<div class="ttlist"><a href="./(.*?.htm)" target="_blank">'
grades = re.compile(pat1,re.S).findall(r.text) #将网页中的网址都爬取下来。
grades=list(set(grades)) #去重复元素
return grades
except:
print("爬取错误")
successful_url=[] #保存已经爬取的网页。
def get_data(html,x):
print('第 ', x ,' 次')
conn=sqlite3.connect('People_education.db')
c=conn.cursor()
try:
r = requests.get(html, timeout=30,headers=get_agent())
pat1='>教师中心</a>>><a href="../../../" target="_self">(.*?)</a>>><a'
catalogue1=re.compile(pat1,re.S).findall(r.text)
pat2='首页</a>>><a href="../../../../../" target="_self">(.*?)</a>>><a'
catalogue2=re.compile(pat2,re.S).findall(r.text)
catalogue2=catalogue2[0]
catalogue3=catalogue2[2:]
catalogue2=catalogue2[0:2]
pat3='</a>>><a href="../" target="_self">(.*?)</a></div>'
catalogue4=re.compile(pat3,re.S).findall(r.text)
pat8='<title>\n(.*?)</title>'
name=re.compile(pat8,re.S).findall(r.text)
conn.execute("INSERT INTO Education(id,level1,level2,level3,level4,name) VALUES(?,?,?,?,?,?)",(x,catalogue1[0],catalogue2,catalogue3,catalogue4[0],name[0],))
conn.commit()
pat4='<p align="center"><embed src="./(.*?.swf)'
data1=re.compile(pat4,re.S).findall(r.text)
if(len(data1)!=0):
data1= html[0:-20]+data1[0] #需要下载的文件的网址合成。
d = requests.get(data1, timeout=30,headers=get_agent()) #下载文件时要都带有浏览器的模拟。
with open('D:/计科5181/xinwen.swf','wb')as f:
for chunk in d.iter_content(chunk_size=100):
f.write(chunk)
f.close()
with open("D:/计科5181/xinwen.swf", "rb") as f:
swf=base64.b64encode(f.read()) #将文件转换为字节。
print(len(swf))
f.close()
c.execute("update Education set swf=(?) where id=(?)",(swf,x)) #保存进数据库
pat5='<a href="./(.*?.ppt)'
data2=re.compile(pat5,re.S).findall(r.text)
if(len(data2)!=0):
data2=html[0:-20]+data2[0]
d = requests.get(data2, timeout=30,headers=get_agent())
with open('D:/计科5181/xinwen.ppt','wb')as f:
for chunk in d.iter_content(chunk_size=100):
f.write(chunk)
f.close()
with open("D:/计科5181/xinwen.ppt", "rb") as f:
ppt=base64.b64encode(f.read()) #将文件转换为字节。
f.close()
print(len(ppt))
c.execute("update Education set ppt=(?) where id=(?)",(ppt,x))
pat6='<A href="http://www.pep.com.cn/download/(.*?.zip)"'
data3=re.compile(pat6,re.S).findall(r.text)
if(len(data3)!=0):
data3='http://219.239.238.50:85/'+data3[0]
d = requests.get(data3, timeout=30,headers=get_agent())
with open('D:/计科5181/xinwen.zip','wb')as f:
for chunk in d.iter_content(chunk_size=100):
f.write(chunk)
f.close()
with open("D:/计科5181/xinwen.zip", "rb") as f:
zips=base64.b64encode(f.read()) #将文件转换为字节。
print(len(zips))
f.close()
conn.execute("update Education set zips=(?) where id=(?)",(zips,x))
pat7='<a href="./(.*?.rar)"'
data4=re.compile(pat7,re.S).findall(r.text)
if(len(data4)!=0):
data4=html[0:-20]+data4[0]
d = requests.get(data4, timeout=30,headers=get_agent())
with open('D:/计科5181/xinwen.rar','wb')as f:
for chunk in d.iter_content(chunk_size=100):
f.write(chunk)
f.close()
with open("D:/计科5181/xinwen.rar", "rb") as f:
rar=base64.b64encode(f.read()) #将文件转换为字节。
print(len(rar))
f.close()
conn.execute("update Education set rar=(?) where id=(?)",(rar,x))
conn.commit()
successful_url.append(html)
print("爬取成功!!!\n")
except:
c.execute("delete FROM Education where id=(%d)"%(x))
conn.commit()
print('爬取错误!!!\n')
c.close()
conn.close()
def write_file():
conn=sqlite3.connect('People_education.db')
c=conn.cursor()
c.execute("select * from Education")
x=1
for variate in c.fetchall():
print('第 ',x,' 次')
path1='D:/教育数据包/'+variate[1]
path2=path1+'/'+variate[2]
path3=path2+'/'+variate[3]
path4=path3+'/'+variate[4]
if(not(os.path.exists(path1))): #创建文件夹。
os.mkdir(path1)
if(not(os.path.exists(path2))):
os.mkdir(path2)
if(not(os.path.exists(path3))):
os.mkdir(path3)
if(not(os.path.exists(path4))):
os.mkdir(path4)
if(variate[6]):
path5=path4+'/'+variate[5]+'.ppt'
ppt=base64.b64decode(variate[6]) #将数据保存进文件中
file=open(path5,'wb')
file.write(ppt)
file.close()
if(variate[7]):
path6=path4+'/'+variate[5]+'.zip'
zips=base64.b64decode(variate[7])
file=open(path6,'wb')
file.write(zips)
file.close()
if(variate[8]):
path7=path4+'/'+variate[5]+'.swf'
swf=base64.b64decode(variate[8])
file=open(path7,'wb')
file.write(swf)
file.close()
if(variate[9]):
path8=path4+'/'+variate[5]+'.rar'
rar=base64.b64decode(variate[9])
file=open(path8,'wb')
file.write(rar)
file.close()
print("保存成功!!!")
x+=1
c.close()
conn.close()
while True:
print("1--爬取数据 2--将数据库保存进文件 3-- 显示未爬取网页 4--退出")
sign=input("输入你的选择:")
sign=int(sign)
while sign not in range(1,5):
sign=input("输入错误,请重新输入您的选择:")
sign=int(sign)
if sign==1:
url = 'http://old.pep.com.cn/czsx/jszx/czsxtbjxzy/czsxdzkb_1_1_2/'
for j in range(0,10): #使用循环,避免爬取网址时出错,无法进行下面的爬取。
grades = get_html(url)
x=1
if(len(grades)!=0):
for grade in grades:
grade= url + grade
htmls.append(grade)
for i in range(0,4): #使用循环,将未爬取的网页继续爬取。
time.sleep(10)
for html in htmls:
if html not in successful_url:
time.sleep(0.3)
get_data(html,x)
x+=1
break
time.sleep(10) #延时处理。
elif sign==2:
write_file()
elif sign==3:
print("未爬取的网页如下:")
for html in htmls:
if html not in successful_url:
print(html)
elif sign==4:
print("退出程序!!!")
break
调试过没发现错误。
我使用的是sqlite 数据库,这样方便数据的移植。