最近在实习,同事给我安排了个小任务:写一个爬虫把雪球网上关注度比较高的股票抓下来,每天2点抓一次,然后同时将股票信息通过钉钉推送给他。
我像往常一样用requests抓取页面,但是我发现这样得到的结果和在浏览器中看到的不一样,我找不到我需要的内容。在浏览器中可以看到正常显示的页面数据,但是使用requests得到的结果并没有。
经过百度发现是因为,requests获取的都是原始的HTML文档,而浏览器中的页面则是经过JavaScript处理数据后生成的结果,这些数据的来源有多种,可能是通过Ajax加载的,可能是包含在HTML文档中的,也可能是经过JavaScript和特定算法计算后生成的。
所以如果遇到这样的情况,就要用其他的办法。
1. 请求
进入网页:https://xueqiu.com/
打开Ajax的XHR过滤器,然后在热股榜里一直点“沪深”,“港股或”美股”,就可以看到,会不断有Ajax请求发出。
也就是不断的会有“list.josn?size=8&&_type=....”出现。
选定我们关注的“沪深”。点击该请求,进入详情页面。
可以发现,这是一个GET类型的请求,请求链接为:
https://stock.xueqiu.com/v5/stock/hot_stock/list.json?size=8&_type=12&type=12
请求的参数有3个: size, _type和type
2. 响应
点开Preview观察响应内容:
展开其中一个,可以看到更详细的信息。
3. 实现
# -*-coding:utf-8-*-
from urllib.parse import urlencode
from pyquery import PyQuery as pq
import requests
from bs4 import BeautifulSoup as bs
import os
headers = {
'Host': 'stock.xueqiu.com',
'Referer': 'https://xueqiu.com/',
'X-Application-Context': 'xueqiu-stock-api-rpc:production',
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
}
base_url = 'https://stock.xueqiu.com/v5/stock/hot_stock/list.json?'
def get_stock_list():
params = {
'size': 8,
'_type': 12,
'type': 12
}
url = base_url + urlencode(params)
try:
res = requests.get(url, headers=headers)
if res.status_code == 200:
return res.json()
except requests.ConnectionError as e:
print('Error', e.args)
def parse_info(json):
if json:
items = json.get('data').get('items')
for i in items:
info = {}
info['code'] = i.get('code')
info['name'] = i.get('name')
info['value'] = i.get('value')
yield info
json = get_stock_list()
results = parse_info(json)
for result in results:
print(result)
很遗憾, requests的结果是status_code为400。但是网页却是能够正确响应。
我查了很多博客都没能解决这个问题,最后我把打开这个网页的Cookie加到headers中,发现就可以返回正常结果了。
但是linux下的pycharm无法显示中文,所以显示有点问题。
但结果是正确的啦!