谁说同花顺很难爬?一文带你学会用Python爬取财经动态网页!
前文的爬虫都建立在静态网页基础之上,首先通过请求网站url获取到网页源代码。之后对源代码进行信息提取进而存储即可,本文则针对动态网页进行数据采集,首先介绍Ajax相关理论,之后实战爬取同花顺动态网页,获取个股相关信息。
一、Ajax理论
1.Ajax简介
Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式、快速动态网页应用的网页开发技术,无需重新加载整个网页的情况下,能够更新部分网页的技术。通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
2.Ajax分析
微博网站就是一个比较容易识别的带有Ajax的动态网页,首先打开Dectools工具(调至XHR一栏)和中南财经政法大学的官微网站(
https://m.weibo.cn/u/1216903164),这里选用的是移动端微博,之后选择清空所有内容。
接下来滚动滑轮将页面向下拉,直至清空的XHR一栏出现新的item,点开这个item并选择Preview栏即可发现这里对应的相应内容即为页面新出现的微博,而反观上方网页链接却没有变,此时我们即可判定这是一个经过Ajax请求之后的网页。
3.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进行处理即可得最终数据!
二、网页分析
1.网页概览
有了上文分析之后我们将通过同花顺网页数据采集实战进行实例验证。首先打开网页:http://q.10jqka.com.cn/,如下图:
进一步按F12键打开Devtools后台源代码,鼠标放至第一条目右键检查可展现出源代码中所在位置。
2.Ajax判别
接下来我们通过点击网页下方的下一页,发现网页url没有发生任何变化!此时基本可以判定此网页属于Ajax动态网页。
进一步我们清空Network中所有内容,继续点击下一页至第五页,发现连续弹出三条Name相同内容,可通过General栏获取到请求的url以及请求头的具体内容。
因此我们将此请求url复制放至浏览器中打开,响应内容果然为标准化表格数据,这正是我们想要的内容。
3.Ajax提取
接着我们同样打开源代码,发现为html文档,表明响应内容为网页形式,这与上文微博响应json格式不同,因此之后可以通过网页解析形式获取数据。
三、爬虫实战
1.网页获取
在经过第一部分的理论介绍和第二部分的网页分析之后我们就可以开始编写爬虫代码了,首先导入库,并定义请求头。需要注意一点的是此处的请求头除User-Agent外还需要host、Referer和X-Requested-With参数,要区分与静态网页爬取。
# 导入库import timeimport jsonimport randomimport requestsimport pandas as pdfrom bs4 import BeautifulSoupheaders = { '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_idres = requests.get(url,headers=headers)res.encoding = 'GBK'
2.信息提取
之后就是上文解析库中的内容,此处采用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
3.保存数据
定义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)
4.循环结构
考虑到同花顺多页结构,同时存在反爬,此处同样采用字符串拼接和循环结构遍历多页股票信息,同时通过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请求的异同并找寻规律,规律找到之后即可建立多页请求流程。之后对单独一个响应内容进行处理(具体看响应内容的格式),最后建立起整个循环爬虫结构即可自动化爬取想要的信息。
爬虫完整代码可以在头条号中私信获得。下文将进一步对浏览器模拟行为进行讲解和实战,前文涉及的基础知识可参考下面链接: