前文的爬虫都建立在静态网页基础之上,首先通过请求网站url获取到网页源代码。之后对源代码进行信息提取进而存储即可,本文则针对动态网页进行数据采集,首先介绍Ajax相关理论,之后实战爬取同花顺动态网页,获取个股相关信息。
目录
一、Ajax理论
1.Ajax简介
2.Ajax分析
3.Ajax提取
二、网页分析
1.网页概览
2.Ajax判别
3.Ajax提取
三、爬虫实战
1.网页获取
2.信息提取
3.保存数据
4.循环结构
Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式、快速动态网页应用的网页开发技术,无需重新加载整个网页的情况下,能够更新部分网页的技术。通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
微博网站就是一个比较容易识别的带有Ajax的动态网页,首先打开Dectools工具(调至XHR一栏)和中南财经政法大学的官微网站(https://m.weibo.cn/u/1216903164),这里选用的是移动端微博,之后选择清空所有内容。
接下来滚动滑轮将页面向下拉,直至清空的XHR一栏出现新的item,点开这个item并选择Preview栏即可发现这里对应的相应内容即为页面新出现的微博,而反观上方网页链接却没有变,此时我们即可判定这是一个经过Ajax请求之后的网页。
还是选择同样的条目进入Headers进一步查看信息,可以发现这是一个GET类型的请求,请求url为:https://m.weibo.cn/api/container/getIndex?type=uid&value=1216903164&containerid=1076031216903164&since_id=4479891116113956,即请求的参数有四个:type、value、containerid、since_id,随后接着翻页发现除since_id变化外,其余都不变化,这里可知since_id即为翻页方式。
接下来进一步观察since_id发现上下请求之间的since_id无明显规律,进一步查找可知下一页的since_id在上一页响应中的cardListInfo里,因此可以建立循环联系进一步将动态url循环加至爬虫里。
发起请求获取响应之后进一步分析,可知响应格式为json,因此进一步对json进行处理即可得最终数据!
有了上文分析之后我们将通过同花顺网页数据采集实战进行实例验证。首先打开网页:http://q.10jqka.com.cn/,如下图:
进一步按F12键打开Devtools后台源代码,鼠标放至第一条目右键检查可展现出源代码中所在位置。
接下来我们通过点击网页下方的下一页,发现网页url没有发生任何变化!此时基本可以判定此网页属于Ajax动态网页。
进一步我们清空Network中所有内容,继续点击下一页至第五页,发现连续弹出三条Name相同内容,可通过General栏获取到请求的url以及请求头的具体内容。
因此我们将此请求url复制放至浏览器中打开,响应内容果然为标准化表格数据,这正是我们想要的内容。
接着我们同样打开源代码,发现为html文档,表明响应内容为网页形式,这与上文微博响应json格式不同,因此之后可以通过网页解析形式获取数据。
在经过第一部分的理论介绍和第二部分的网页分析之后我们就可以开始编写爬虫代码了,首先导入库,并定义请求头。需要注意一点的是此处的请求头除User-Agent外还需要host、Referer和X-Requested-With参数,要区分与静态网页爬取。
# 导入库
import time
import json
import random
import requests
import pandas as pd
from bs4 import BeautifulSoup
headers = {
'host':'q.10jqka.com.cn',
'Referer':'http://q.10jqka.com.cn/',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3554.0 Safari/537.36',
'X-Requested-With':'XMLHttpRequest'
}
url = 'http://q.10jqka.com.cn/index/index/board/all/field/zdf/order/desc/page/%s/ajax/1/' % page_id
res = requests.get(url,headers=headers)
res.encoding = 'GBK'
之后就是上文解析库中的内容,此处采用BaetifulSoup库更易于理解。先将上文html转化为BeautifulSoup对象,之后通过对象的select选择器选择响应tr标签内的数据,并进一步解析每一条tr标签的内容即可得到以下相应信息。
# 获取单页数据
def get_html(page_id):
headers = {
'host':'q.10jqka.com.cn',
'Referer':'http://q.10jqka.com.cn/',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3554.0 Safari/537.36',
'X-Requested-With':'XMLHttpRequest'
}
url = 'http://q.10jqka.com.cn/index/index/board/all/field/zdf/order/desc/page/%s/ajax/1/' % page_id
res = requests.get(url,headers=headers)
res.encoding = 'GBK'
soup = BeautifulSoup(res.text,'lxml')
tr_list = soup.select('tbody tr')
# print(tr_list)
stocks = []
for each_tr in tr_list:
td_list = each_tr.select('td')
data = {
'股票代码':td_list[1].text,
'股票简称':td_list[2].text,
'股票链接':each_tr.a['href'],
'现价':td_list[3].text,
'涨幅':td_list[4].text,
'涨跌':td_list[5].text,
'涨速':td_list[6].text,
'换手':td_list[7].text,
'量比':td_list[8].text,
'振幅':td_list[9].text,
'成交额':td_list[10].text,
'流通股':td_list[11].text,
'流通市值':td_list[12].text,
'市盈率':td_list[13].text,
}
stocks.append(data)
return stocks
定义write2excel函数将数据保存至stocks.xlsx文件中。
# 保存数据
def write2excel(result):
json_result = json.dumps(result)
with open('stocks.json','w') as f:
f.write(json_result)
with open('stocks.json','r') as f:
data = f.read()
data = json.loads(data)
df = pd.DataFrame(data,columns=['股票代码','股票简称','股票链接','现价','涨幅','涨跌','涨速','换手','量比','振幅','成交额', '流通股','流通市值','市盈率'])
df.to_excel('stocks.xlsx',index=False)
考虑到同花顺多页结构,同时存在反爬,此处同样采用字符串拼接和循环结构遍历多页股票信息,同时通过random库中randint方法和time库的sleep方法间断一定时长再进行爬取。
def get_pages(page_n):
stocks_n = []
for page_id in range(1,page_n+1):
page = get_html(page_id)
stocks_n.extend(page)
time.sleep(random.randint(1,10))
return stocks_n
最终的爬取结果如下:
至此同花顺动态网页的爬取完成,再通过此爬虫总结一下:首先我们通过浏览网页结构和翻页对比XHR栏对改网页进行Ajax判定,如果网页url不变且XHR会刷新内容则基本表明为动态网页,此时我们进一步查看多页间url请求的异同并找寻规律,规律找到之后即可建立多页请求流程。之后对单独一个响应内容进行处理(具体看响应内容的格式),最后建立起整个循环爬虫结构即可自动化爬取想要的信息。
爬虫完整代码可以在公众号中回复“同花顺”获得。下文将进一步对浏览器模拟行为进行讲解和实战,前文涉及的基础知识可参考下面链接:
Python网络爬虫数据采集实战:基础知识
Python网络爬虫数据采集实战:Requests和Re库
Python网络爬虫数据采集实战:豆瓣电影top250爬取
Python网络爬虫数据采集实战:网页解析库