gingingg
- 关注
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9

1.urllib模块学习
request方法.
urlretrieve()将网页直接下载到本地中
urlcleanup()将爬虫产生的缓存删除
info()查看网页的一些简介信息
getcode()输出网页的状态码
geturl()获取当前访问的网页url
import urllib.request
# urlretrieve(网址,本地文件存储地址)直接下载网页到本地
urllib.request.urlretrieve("http://www.baidu.com", "C:\\Users\\...\\Desktop\\1.html")
urllib.request.urlcleanup()
# 看网页相关简介信息
file = urllib.request.urlopen("http://www.baidu.com")
print(file.info())
# 返回网页爬取的状态码
print(file.getcode())
# 获取当前访问的网页url,geturl()
print(file.geturl())
运行结束后,可以看到桌面创建的1.html文件打开后,是百度的原始界面,但是看到路径可以知道是本地的
2.超时设置
当爬取一个网站时,需要时间。访问一个网页时,若长时间无响应,系统就会判断超时,无法打开网页。
我们可以通过设置timeout参数时设置超时时间,超过相应时间就会判断超时。
#超时设置
import urllib.request
for i in range(0,100):
file=urllib.request.urlopen("http://www.baidu.com",timeout=1) #设置超时时间为1
try:
print(file.read)
except Exception as err:
print("出现异常")
但是此时一次可能会相应正常,多试几次之后才可以看出是否出现超时异常,而timeout函数配合try函数使用可以更好的运行,显示超时异常时,也可以跳过此时继续运行
3.自动模拟http请求
1)get请求
客户端利用http请求的方式进行访问,常见有我们熟知的get与post请求
#get请求实战---实现edge信息自动搜索
import urllib.request
import re
keywd="lidalu"
Keywd=urllib.request.quote(keywd)
#page=(num-1)*10
for i in range(1,11):
url="https://cn.bing.com/search?q="+keywd+"&pn="+str((i-1)*10)
date=urllib.request.urlopen(url).read().decode("utf-8")
pat="title:'(.*?)',"
pat2='"title":"(.*?)",'
rst=re.compile(pat).findall(date)
rst1=re.compile(pat2).findall(date)
for i in range(0,len(rst)):
print(rst[i])
for i in range(0,len(rst1)):
print(rst1[i])
本来想实现百度引擎的搜索,但是出了一些问题,所以改成edge来进行搜索。
通过改变keywd与range内的值来爬取,搜索结果及对应的title名
及时理解就好,有时一些大型网站对于爬虫会有反爬技术支持,返回一个空字符,不是代码问题而是响应问题,也有可能是cookie等的问题。
2)post请求
#post请求实战
import urllib.request
import urllib.parse
posturl="目标post url"
postdate=urllib.parse.urlencode({
"key":"??????",#利用字典的方法定义post参数(键值对)
"value":"?????",
}).encode("utf-8")
#需要使用urllib.request下面的Request(post地址,post数据)
req=urllib.request.Request(posturl,postdate)#如前面定义的数据,url+post参数形式,将请求发送
rst=urllib.request.urlopen(req).read().decode("utf-8")#利用urlopen方法读取呈现返回内容
可以看出利用python写脚本真的很简单,无需定义任何方法,大部分时候利用模块中的方法都可以搞定,所以现在我们需要熟悉各种方法的使用过程
4.爬虫异常处理
前文写过,一个异常处理的方法,学习网安的同志们都明白状态码对应的含义,平时在渗透的时候也见惯了40?,50?,有时我们会束手无策,同样的,当我们不进行设置异常处理时,见到错误状态码或者拒绝访问,爬虫也会崩溃停止运行,所以我们需要设置异常处理来处理跳过错误或应对错误。
1)常见状态码总结(大佬跳过)
301 永久性重定向到新的url(一般用于防止查看敏感目录文件而重定向于主页,一般会呈现界面但是结果不尽人意)
302 重定向到临时url
400 非法请求(想必这个不用多说了)
401 未授权访问
403 禁止访问
404 未找到页面或页面丢失
500 服务器内部错误,可能已经删库跑路了
501 服务器不支持请求功能
2)URLError与HTTPError
都是异常处理的类,但是HTTPError是URLError的子类,HTTPError有异常状态码与异常原因,URLError没有异常状态码,处理的时候,无法直接使用URLError直接代替HTTPError。代替之前要先判断是否含有状态码属性。
也就意味着任何时候都可以使用HTTPError。
#异常处理
'''
引起URLError常见原因
1)连不上服务器
2)地址不存在
3)无网络
4)触发了HTTPError(URLError是HTTPError的父类)
'''
#利用是否含有状态码判断URLError
import urllib.request
import urllib.error
try: #处理异常函数
urllib.request.urlopen("目标url")
except urllib.error.URLError as e:
if hasattr(e,"code"): #判断是否含有状态码,含有则返回
print(e.code)
if hasattr(e,"reason"): #返回错误原因
print(e.reason)
5.爬虫浏览器伪装技术
很多时候爬取博客的时候会发现返回403,因为服务器会对爬虫进行屏蔽。所以此时我们需要伪装成浏览器才能爬取。
其实原理就是通过伪装报头进行的。
urlopen()对于一些HTTP高级功能不进行支持,所以,需要修改报头,所以使用urllib.request.build_opener()进行,也可以使用urllib.request.Request()下的add_header()实现浏览器模拟
#浏览器伪装,创建一个请求,加入伪造的报头,目标url进行访问目标网站,爬取相应内容
import urllib.request
url="目标url"
#头文件格式header=("User-Agent",具体用户代理值)
headers=("User-Agent","伪造的ua头")
opener=urllib.request.build_opener()
opener.addheaders=[headers]
data=opener.open(url).read()
fh=open("存放路径","wb")#以二进制存储
fh.write(data)
fh.close()
6.综合爬虫的编写
1)对于某浏览器伪装并爬取页面中url对应的页面信息
#一个综合爬虫
'''
1.爬取新闻首页
2.得到各新闻链接
3.爬取新闻链接
4.寻找有没有frame
'''
import urllib.request
import re
url="http://news.xx.com"
#头文件格式header=("User-Agent",具体用户代理值)
headers=("User-Agent","伪造的ua头")
opener=urllib.request.build_opener()
opener.addheaders=[headers]
data=opener.open(url).read()
pat1='<a target="_blank" class="linkto" href="(.*?)"'
alllink=re.compile(pat1).findall(data)#爬取首页中的所有url
for i in range(0,len(alllink)):
try:
thislink=alllink[i]
thispage=urllib.request.urlopen(thislink).read().decode("UTF-8","ignore")#爬取首页中所有url对应网址内的内容
pat2="<frame src=(.*?)>"#判断是否含有frame
isframe=re.compile(pat2).findall(thispage)
if(len(isframe)==0):
#直接爬
print(i)
urllib.request.urlretrieve(thislink,"目标路径")
else:
#得到frame的网址爬
flink=isframe[0]
urllib.request.urlretrieve(flink,"目标路径")
except Exception as err:
print(err)
可以利用这个爬取一些网站的首页内容以及对应url对应网页的内容
兄弟们可以理解一下,其实大部分第一次爬取还不用进行伪造,但是我这次加上了(为了凑字数)
2)**百科爬虫
'''
**百科爬虫
'''
import urllib.request
import re
headers=("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0")
opener=urllib.request.build_opener()
opener.addheaders=[headers]
#安装为全局
urllib.request.install_opener(opener)
for i in range(0,35):
thisurl="http://www.????.com/8hr/page"+str(i+1)+"/?s=4948859" #正则语句中描述页码数,根据url而构造
data=urllib.request.urlopen(thisurl).read().decode("utf-8","ignore")
pat='<div dlass="content">.*?<span>(.*?)</span>.*?</div>'
rst=re.compile(pat,re.S).findall(data)
for i in range(0,len(rst)):
print(rst[i])
print("----------")
7.用户代理池
之前已经写过如何进行用户代理了,但是何谓用户代理池?顾名思义,就是将多个用户代理构建在一起,随机调用。
#用户代理池的构建
import urllib.request
import re
import random #实现随机选择的模块
uapools=[
用户代理1
用户代理2
用户代理3
] #实现多个浏览器ua头进行访问
def ua(uapools):
rst=random.choice(uapools) #random随机访问函数
print(rst)
headers = ("User-Agent", rst) #将rst赋值给访问的ua头
opener = urllib.request.build_opener()
opener.addheaders = [headers]
# 安装为全局
urllib.request.install_opener(opener)
for i in range(0,35):
ua(uapools) #访问之前首先利用随机的用户代理访问目标网页
thisurl="http://www.qiushibaike.com/8hr/page"+str(i+1)+"/?s=4948859"
data=urllib.request.urlopen(thisurl).read().decode("utf-8","ignore")
pat='<div dlass="content">.*?<span>(.*?)</span>.*?</div>'
rst=re.compile(pat,re.S).findall(data)
for i in range(0,len(rst)):
print(rst[i])
print("----------")
8.ip代理及构建代理池
ip代理,可以通过代理网站或软件进行生成
1)ip代理构建
#ip代理构建
import urllib.request
ip="代理ip:端口" #将找到的代理ip进行构建
proxy=urllib.request.ProxyHandler({"http":ip}) #构键opener对象进行构建伪造信息
opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler)
urllib.request.install_opener(opener)
url="目标url" #按部就班进行访问,爬取信息装入目标文件
data=urllib.request.urlopen().read().decode("utf-8","ignore")
print(len(data))
fh=open("将爬取的信息保存的路径","wb")
fh.write(data)
fh.close()
2)ip代理池构建(方法一)
方法一是直接在网站上找到固定的ip,并构造成一个ip代理池,因为是固定的,所以临时ip可能会出现失效的情况
#ip代理池构建1(适用于代理ip稳定的情况)
import random
import urllib.request
impools=[
"代理ip1"
"代理ip2"
"代理ip3"
] #直接将找到的ip呈现为一个列表,并可以随机进行构建
def ips(impools): #构建函数可以随机选取ip
rst=random.choice(impools)
print(rst)
proxy = urllib.request.ProxyHandler({"http": rst})
opener = urllib.request.build_opener(proxy, urllib.request.HTTPHandler)
urllib.request.install_opener(opener)
for i in range(0,3): #利用构建好的头进行三次访问
try: #添加报错函数进行爬取
ips()
url = "目标url"
data = urllib.request.urlopen().read().decode("utf-8", "ignore")
print(len(data))
fh = open("将爬取的信息保存的路径", "wb")
fh.write(data)
fh.close()
except Exception as err:
print(err)
3)ip代理池构建(方法二)
方法二是直接利用爬虫访问提供ip代理网站的url,进行构造url来获取随机的代理ip,可以实现即用即取,不会发生时效性问题,但是可能会出现访问失败的情况,而且很多网站对于国内ip会有一定限制,而且代理ip网站的国内代理ip会有很大失效性可能,所以推荐适用国外代理ip
#ip代理池构建2(接口调用的方法:适用于代理ip不稳定的情况)
import random
import urllib.request
def ip():
thisip=urllib.request.urlopen("提供代理ip网站url").read().encode("utf-8","ignore")
print(thisip)
proxy=urllib.request.ProxyHandler({"http":thisip})
opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler)
urllib.request.install_opener(opener)
for i in range(0,3):
try:
ip()
url = "目标url"
data = urllib.request.urlopen().read().decode("utf-8", "ignore")
print(len(data))
fh = open("将爬取的信息保存的路径", "wb")
fh.write(data)
fh.close()
except Exception as err:
print(err)
9.一个图片爬取爬虫
#某宝商品图片爬虫
import urllib.request
import re
import random
eyname="连衣裙" #设置关键词参数
ey=urllib.request.quote(eyname) #将kyname为中文时的参数进行转码
uapools=[
用户代理1 #设置用户代理池
用户代理2
用户代理3
]
def ua(apools): #创建一个利用用户代理池随机ua头访问目标网址
thisua=random.choice(apools)
print(thisua)
headers=("User-Agent",thisua)
opener=urllib.request.build_opener()
opener.addheaders=[headers]
#安装为全局
urllib.request.install_opener(opener)
for i in range(1,101): #创建循环进行访问
url="构造目标url"
ua(uapools)
data=urllib.request.urlopen(url).read().decode("utf-8","ignore")
pat='"pic_url":"//(.*?)"' #在网页源码中找到图片对应的前后对应构造正则进行匹配爬取
imglist=re.compile(pat).findall(data)
for j in range(0,len(imglist)): #构造文件将爬取的图片循环保存至本地
thisimg=imglist[j]
thisimgurl="http://"+thisimg
localfile="设置本地保存图片的地址"
urllib.request.urlretrieve(thisimgurl,filename=localfile)
10.小总结
这两天进行的学习我们可以发现其实爬虫就是按部就班那几步,但是我认为更加重要的是,其实是对于网页中url与正则的构造
这也是我们代码审计时重要的一点,更好的构造与观察
构造主要url:
在某宝搜索物品时url是这样的:
https://uland.taobao.com/sem/tbsearch?refpid=mm_26632258_3504122_32538762&keyword=%E8%BF%9E%E8%A1%A3%E8%A3%99&clk1=05ca67a536bec1378efe2c7183615bb3&upsId=05ca67a536bec1378efe2c7183615bb3&spm=a2e0b.20350158.search.1&pid=mm_26632258_3504122_32538762&union_lens=recoveryid%3A201_11.92.48.7_45721226_1639024828287%3Bprepvid%3A201_11.92.48.7_45721226_1639024828287
此时我们需要对于返回的url进行一个筛选与观察,不同参数代表的含义以及目标参数位置,比如我们常用的搜索目标与页码
这样直接观察很难直接进行判断,所以我们此时翻页继续进行观察url变化
https://uland.taobao.com/sem/tbsearch?refpid=mm_26632258_3504122_32538762&keyword=%E8%BF%9E%E8%A1%A3%E8%A3%99&clk1=05ca67a536bec1378efe2c7183615bb3&upsId=05ca67a536bec1378efe2c7183615bb3&spm=a2e0b.20350158.31919782.1&pid=mm_26632258_3504122_32538762&union_lens=recoveryid%3A201_11.92.48.7_45721226_1639024828287%3Bprepvid%3A201_11.92.48.7_45721226_1639024828287&pnum=1
https://uland.taobao.com/sem/tbsearch?refpid=mm_26632258_3504122_32538762&keyword=%E8%BF%9E%E8%A1%A3%E8%A3%99&clk1=05ca67a536bec1378efe2c7183615bb3&upsId=05ca67a536bec1378efe2c7183615bb3&spm=a2e0b.20350158.31919782.1&pid=mm_26632258_3504122_32538762&union_lens=recoveryid%3A201_11.92.48.7_45721226_1639024828287%3Bprepvid%3A201_11.92.48.7_45721226_1639024828287&pnum=2
这是前三页所对应的url:
观察得知pnum参数对应的是页码,是从0开始计算,而为0时是不显示的,即默认为0,就像我们平时浏览web服务默认8080端口是不显示的
同样的此时我们也无法得知搜值对应的参数
大多网站对于中文返回时会进行编码,这也是我们在写爬虫时对于中文搜索值会进行转码
于是此时我们可以利用英文参数进行判断搜索值对应的参数
https://uland.taobao.com/sem/tbsearch?refpid=mm_26632258_3504122_32538762&keyword=python&clk1=05ca67a536bec1378efe2c7183615bb3&upsId=05ca67a536bec1378efe2c7183615bb3&spm=a2e0b.20350158.search.1&pid=mm_26632258_3504122_32538762&union_lens=recoveryid%3A201_11.92.48.7_45721226_1639024828287%3Bprepvid%3A201_11.11.144.128_43717936_1639025004080
由此可见,搜索值决定的参数就是keyword,此时我们就可以直接构造主要url进行利用
https://uland.taobao.com/sem/tbsearch?keyword=python&pnum=?
其他参数对应改变的值可能各不相同,但是我们只需要此时利用的参数即可,同样的在我们平时进行渗透测试时也是一个不错的技巧
构造正确的正则
在我们爬取图片时,需要将图片对应网址首先从网页对应源码中爬取出来,之后再利用爬虫对网址进行访问,爬取,那么正确构造正则也是一个关键
打开源码进行目标的搜索例如搜索img
观察其对应前后的语句例如
<a href="#"><img data-src="//gd4.alicdn.com/imgextra/i4/742348417/O1CN01aAhKyR2C32Ojr6N5B_!!0-item_pic.jpg_50x50.jpg" /></a>
此时我们就可以针对这个html语句构造对应的正则语句,而我们所需要的就是这段
//gd4.alicdn.com/imgextra/i4/742348417/O1CN01aAhKyR2C32Ojr6N5B_!!0-item_pic.jpg_50x50.jpg
所以可以这样构建
pat='< img data-src="(.*?)"/ >'
其中()是只将()中的值赋给pat,而.是代表任意值,*是代表多次匹配,?代表全局匹配
这是我认为复习到现在需要注意的两点,多多利用就可以如鱼得水了。
好好学习,天天向上!
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
