最近公司接了一个项目,客户需要对某一网址进行数据爬虫,这是我第一次接触爬虫,也是我第一次使用Python语言,小白上路,写的不是很好,技术也不是很新,各位大佬轻喷!
爬虫步骤
Created with Raphaël 2.3.0 开始 获取URL 发送请求 获取响应 解析数据 结束
获取URL
根据客户需求对需要爬行的网址进行分析,由于某些原因我会对图片打码!
进入页面打开浏览器控制台,选择Network查看调用的数据接口
通过对API逐一查看分析,可以发现此API是直接以html的形式进行响应而且里面的数据也都进行了渲染,这样我们就获取到了URL
发送请求
发送请求,一般由请求方式(get,post)、请求头、请求体组成。
我们继续查看刚刚的API里的headers部分查看请求信息
这边我们可以看到URL地址、请求方式、请求头信息以及响应头信息,在这里面我们可以关注几个重要的属性,请求头里的cookie、User-Agent(简单说就是浏览器属性)。
这里将要着重分析cookie的值,cookie是由服务器返回给客户端的,因此我们可以在控制台的network中ctrl+F搜索set-cookie
这里我们可以看到返回的cookie信息,或者在控制台中也可以查看当前的cookie
我们来看响应头里有cookie信息的URL,继续分析它的URL以及请求头等信息,在URL中我们可以看到路径里的参数有tokenId,并且每次登录的时候这个值都会变,通过对值的搜索可以发现这是cookies中某一个属性。此时就很纳闷了,请求也有这个,响应也有这个,这个值怎么来的都不知道。
找来找去实在是找不到了,我只好去查看登录按钮的响应事件,打开控制台用左上角的箭头定位登录按钮的代码
可是html代码并没有click事件属性,那么肯定是在js中绑定了click事件,可以看到这里有class属性,于是我们对此属性的值进行全局搜索,ctrl+shift+f进行全局搜索
可以看到使用Jquery绑定了click事件,然后进入代码块,认真分析js代码,这里我就不贴图了,在js登录函数中我们发现了ajax请求,那么可以再次搜索这个url,我们可以在这打一个断点,查看响应的数据内容
通过断点调试,发现响应的数据中有一条数据与刚刚获取cookie的url是一样的,因此我们就可以知道获取cookie的整个流程了。接下来上代码!!
from http import cookiejar
from urllib import request
from log import logger
import requests
import time
import json
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36", # 一定要加这是反爬虫的第一步
"Host":""
}
# 参数:毫秒级时间戳
def getcookie():
# 获取当前时间戳
t = time.time()
# 秒级时间戳
ts = str(int(t))
# 毫秒级时间戳
tms = str(int(round(t * 1000)))
# 先调用登录接口获取登录成功跳转接口获取cookie
pwdurl = ''
response = requests.get(pwdurl, headers=headers)
# 获取到跳转链接
jumpto = json.loads(response.text)['data']['jumpTo']
logger.info("cookie跳转地址:" + jumpto)
response = requests.get(jumpto, headers=headers)
# 获取cookie
# 声明一个CookieJar对象实例来保存cookie
cookie = response.cookies
# # 打印cookie信息
cookieMap = {}
for item in cookie:
cookieMap[item.name] = item.value
logger.info("Cookie数据:%s",cookieMap)
newheaders = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36",
"Cookie": ''
}
return newheaders
有了url和cookie等一些信息之后我们可以发送请求了
import requests
response = requests.get(url, headers=headers)
response.encoding = 'gb2312' # 网页是gb2312编码 可以在原码中查看
return response
响应数据处理
获取到相应内容之后,进行解析内容,有两种解析方式,运用bs4库中的BeautifulSoup进行解析或者lxml库中的etree解析成树状html
运用bs4库中的BeautifulSoup进行解析
bsObj = BeautifulSoup(response.text, "lxml") #以lxml方式解析,速度快还有其他方式 自行搜索比较
# 解析完response之后需要捕捉数据,可以使用正则表达式
pattern = re.compile('https(.*?)123')
r = re.search(pattern, str(bsObj)).group(1)
etree解析成树状html
# 解析完成之后我们可以用xpath进行匹配,这个非常的方便 但是并不灵活,页面排版变了就失效了
tree = etree.HTML(response.text)
# 可以在浏览器控制台中
jiage = tree.xpath('normalize-space(//*[@id="ctr1"]/td[3]/text())') # normalize-space 去除空格,text()获取文本
反爬手段
本次爬虫我遇到了一个反爬虫手段——数字加密
图一页面内容,图二源码内容,可以发现数据不一样,通过分析是由于css里的字体属性导致的
通过搜索,我们可以获取到字体的链接,我们使用ttf格式的链接,将字体文件保存到本地并进行分析
wzresponse = requests.get(wzaddress, headers=headers).content
with open('./fonts.ttf', 'wb') as f:
f.write(wzresponse)
# 解析字体
font = TTFont('./fonts.ttf')
font.saveXML('fonts.xml') # 转换成xml---方便自己查找规律 不加也可以
uniMap = font['cmap'].tables[0].ttFont.getBestCmap()
csswz = list(uniMap.values())[1:11]
logger.info("css样式字体顺序:" + str(csswz))
uni_list = font.getGlyphOrder()
truewz = uni_list[2:12]
logger.info("实际字体顺序:" + str(truewz))
结语
通过这个爬虫,个人觉得代码层面是不难的,难在请求参数的解析,cookie的解析,js逆向,登录验证码解析等各种反爬虫手段,不过道高一尺,魔高一丈,总归有解决的办法!!! 其次文章中,对于cookie的值我并没有进行讲解,这个根据自己实际需求进行测试,那么多的cookie不可能全都有用,大家可以通过postman对cookie的值进行删减直到获取不到数据为之!总的说请求头信息,cookie等信息并不是全部都需要传递!