空闲的时候随便找了一个网站练习一下爬虫,总结一下自己写爬虫遇到的知识点
实现的功能
抓取全站URL
获取CSS,JS, img等文件连接
获取文件名字
保存文件到本地
用到的模块
urllib
bs4
re
os
第一部分:抓取全站URL
先贴上代码
# 获取当前页面子网站子网站
def get_urls(url, baseurl, urls):
with request.urlopen(url) as f:
data = f.read().decode('utf-8')
link = bs(data).find_all('a')
for i in link:
suffix = i.get('href')
# 设置排除写入的子连接
if suffix == '#' or suffix == '#carousel-example-generic' or 'javascript:void(0)' in suffix:
continue
else:
# 构建urls
childurl = baseurl + suffix
if childurl not in urls:
urls.append(childurl)
# 获取整个网站URL
def getallUrl(url, baseurl, urls):
get_urls(url, baseurl, urls)
end = len(urls)
start = 0
while(True):
if start == end:
break
for i in range(start, end):
get_urls(urls[i], baseurl, urls)
time.sleep(1)
start = end
end = len(urls)
通过urllib包中的request,调用urlopen对网站进行访问
首先从首页开始,首页里面一般包含各个子页面的URL,把抓取到的URL添加到一个列表里面
然后再读取这个列表的每个元素,依次进行访问,获取子页面上的url连接添加到列表。
感觉这样抓取整站URL不是很靠谱,有时间会完善下
第二部分:获取css,js,img的连接
先贴上代码
# 获取当前网页代码
with request.urlopen(url) as f:
html_source = f.read().decode()
# css,js,img正则表达式,以获取文件相对路径
patterncss = '<link rel="stylesheet" href="(.*?)"'
patternjs = '<script src="(.*?)"'
patternimg = '<img src="(.*?)"'
titleStr = re.compile(pattertitil
# 使用re模块通过正则规则获取相对路径
cssHerf = re.compile(patterncss, re.S).findall(html_source)
jsHref = re.compile(patternjs, re.S).findall(html_source)
imgHref = re.compile(patternimg, re.S).findall(html_source)
然后基于网站地址 + Href即可获得各个文件的地址
第三部分:获取文件名字
这里其实用python的split()就可以解决,我作死用了一个早上去写正则,就写出了css的正则。
代码如下
path需提前传进来
# 获取css文件名并选择本地保存路径(使用了正则)
patternCssTitle = '(/?.*?.css?)'
filename = path + '\\' + re.compile(patternCssTitle, re.S).findall(url)[1][1:]
# 使用split方法
filename = path + '\\' + href[i].split('/')[-1]
# 获取js文件名并选择本地保存路径
filename = path + '\\' + href[i].split('/')[-1]
# 获取img文件名并选择本地保存路径
filename = path + '\\' + href[i].split('/')[-1]
第四部分:保存文件到本地
使用pythonIO进行读写操作,为防止出错采用了try..except..
# 保存html
try:
with open(filename, 'w') as f:
f.write(html_source)
except:
print("文件无法保存,请检查参数配置")
exit(1)
# 保存CSS文件
try:
with request.urlopen(url) as w:
css_source = w.read().decode()
with open(filename, 'w') as f:
f.write(css_source)
print(re.compile(patternCssTitle, re.S).findall(url)[1][1:] + " css文件保存成功!")
time.sleep(1)
except:
print("该" + re.compile(patternCssTitle, re.S).findall(url)[1][1:] + " css文件无法下载")
# 保存js文件
try:
with request.urlopen(url) as w:
js_source = w.read().decode()
with open(filename, 'w') as f:
f.write(js_source)
print(href[i].split('/')[-1] + " js文件保存成功")
time.sleep(1)
except:
print("该" + href[i].split('/')[-1] + " js文件无法下载")
# 这里使用continue是因为遇到cdn的js文件报错没办法保存,直接跳过
continue
在保存图像的时候我没有使用decode()
# 保存img文件
try:
with request.urlopen(url) as w:
img_source = w.read()
with open(filename, 'wb') as f:
f.write(img_source)
print(href[i].split('/')[-1] + " 图像文件保存成功")
time.sleep(1)
except:
print("该" + href[i].split('/')[-1] + " 图像无法下载")
采用with(),防止读写文件时没有关闭
其实还有另外一种方法获取文件和代码,从腾讯云上面看到的,但是我尝试了就打开了浏览器后面没有进行保存。
* 出处https://cloud.tencent.com/developer/ask/49008
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
br = webdriver.Firefox()
br.get('http://www.google.com/')
save_me = ActionChains(br).key_down(Keys.CONTROL)\
.key_down('s').key_up(Keys.CONTROL).key_up('s')
save_me.perform()