freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

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

好玩的爬虫小玩意(3)----浏览器伪装
gingingg 2021-12-31 16:31:24 568720
所属地 山西省

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,而.是代表任意值,*是代表多次匹配,?代表全局匹配

这是我认为复习到现在需要注意的两点,多多利用就可以如鱼得水了。


好好学习,天天向上!

# python # 爬虫
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 gingingg 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
好玩的爬虫
gingingg LV.4
不定时更新
  • 13 文章数
  • 17 关注者
GlodenEye-v1黄金眼靶场复现
2022-11-25
Dockerfile搭建靶场与Docker技巧
2022-11-09
渗透测试之路:WebLogic中间件漏洞复现
2022-01-13