运用 Python 爬取私募基金信息_request

2018.11.22

爬虫要求:
目标 url:http://gs.amac.org.cn/amac-infodisc/res/pof/fund/index.html
抓取信息:每条基金的 基金名称 私募基金管理人名称 托管人名称 成立时间 备案时间
基金具体url。
即下图信息+url 链接
在这里插入图片描述

一、环境
安装好 Anaconda(Python 版本为 3.6)即可,较简单,教程较多,如:https://www.jianshu.com/p/62f155eb6ac5
不过我建议大家可以勾选“Add Anaconda to my PATH environment variable.”(“添加Anaconda至我的环境变量。”),自行决定,我勾选了,省的环境变量出错。

二、分析

打开目标网页,右键选择查看源代码,发现需要爬取的信息在源代码中没有显示,比如‘嘉兴全意投资合伙企业’,在源代码中搜索不到。并且当更换页数时,网页 url 并没有改变。此种情况,应该是网页的内容是由 JavaScript 渲染而成,请求 url 返回的是一些 JavaScript 代码。怎么办?两种思路:

  • 运用 Selenium 库,所见即所爬!(网页上看到什么就能爬取什么,但是目前淘宝等网页有针对 Selenium 进行的反爬,但是也有相应的绕过反爬的方法,此处不细说)但是 Selenium 致命缺点是,效率!因为是模拟出浏览器的实际操作,所以在爬取的效率上比较低,而且占用电脑的操作。
  • 分析接口参数,找到网页请求的实际 url,然后再进行请求。

三、 实战
方法 1:
占坑。
填坑,贴下代码,含注释,写的比较糙,懒得改了。若是未安装 Selenium 模块,需要在 anaconda 控制台输入conda install selenium 来安装该模块,同时,我用的是 Chrome 浏览器,并且还要安装 Chrome Driver。

from selenium import webdriver
from selenium.webdriver.support.select import Select
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from lxml import etree
import time
import openpyxl

browser = webdriver.Chrome()  # 创建一个谷歌浏览器对象
browser.get('http://gs.amac.org.cn/amac-infodisc/res/pof/fund/index.html')  # 打开网址
wait = WebDriverWait(browser,10)  # 设置最长等待时间 10s 
option_100=browser.find_element_by_xpath('//*[@id="fundlist_length"]/label/select') # 找到每页显示100 条 的位置
Select(option_100).select_by_value('100')  # 选择每页显示 100 条
wait.until(EC.text_to_be_present_in_element((By.XPATH,'//*[@id="fundlist"]/tbody/tr[100]/td[1]'),'100')) # 等待第100 个信息加载出来
button = wait.until(EC.presence_of_element_located((By.XPATH,'/html/body/div[6]/div[3]/div/button[@style="color: rgb(85, 85, 85);"]'))) # 等待 关闭 按钮加载出来
button.click()  # 点击关闭按钮
input = wait.until(EC.presence_of_element_located((By.XPATH,'//*[@id="goInput"]'))) # 等待 选择页数 输入框加载出来
lis = [] # 创建一个列表,用来存放字典
for page in range(1,100):  # 爬取页数 范围设置
	input.clear() # 清除页数输入框内内容
	input.send_keys(str(page)) # 向框内填写 page
	button = browser.find_element_by_xpath('//*[@id="fundlist_paginate"]/button') # 找到 转到 按钮
	button.click() # 点击按钮
	wait.until(EC.text_to_be_present_in_element((By.XPATH,'//*[@id="fundlist_paginate"]/span//a[@active="true"]'),str(page))) # 等待该页高亮显示出来

	text = browser.page_source  # 获取该页 源码
	selector = etree.HTML(text) # 创建 XPATH 选择器
	
	for i in range(1,101):  # 爬取该页的条数的范围
		dic = {} # 创建一个字典,存放信息
		num = selector.xpath('//*[@id="fundlist"]/tbody/tr[%d]/td[1]/text()'%i)[0]  # 编号
		name = selector.xpath('//*[@id="fundlist"]/tbody/tr[%d]/td[2]/a/text()'%i)[0]  # 名称
		name2 = selector.xpath('//*[@id="fundlist"]/tbody/tr[%d]/td[3]/a/text()'%i)[0] # 私募基金管理人名称
		manager = selector.xpath('//*[@id="fundlist"]/tbody/tr[%d]/td[4]//text()'%i) # 托管人名称
		if not manager:
			manager = ''
		else:
			manager = manager[0]
		time1 = selector.xpath('//*[@id="fundlist"]/tbody/tr[%d]/td[5]/text()'%i) # 成立时间
		if not time1:
			time1 = ''
		else:
			time1 = time1[0]
		time2 = selector.xpath('//*[@id="fundlist"]/tbody/tr[%d]/td[6]/text()'%i) # 备案时间
		if not time2:
			time2 = ''
		else:
			time2 = time2[0]
		# 将信息存入字典中
		dic['num']=int(num)+(page-1)*100
		dic['name']=name
		dic['name2']=name2
		dic['manager']=manager
		dic['time1']=time1
		dic['time2']=time2
		lis.append(dic)  # 将字典存入列表中
# print(lis)
browser.close()  # 关闭浏览器
# '''
excel = openpyxl.Workbook() # 创建 excel
sheet = excel.active  # 找到当前页
length = len(lis) # 列表长度,即共抓取多少条信息
# 设置表头
sheet['A1'] = '编号'
sheet['B1'] = '基金名称'
sheet['C1'] = '私募基金管理人名称'
sheet['D1'] = '托管人名称'
sheet['E1'] = '成立时间'
sheet['F1'] = '备案时间'
# 将爬取到的信息存放到 excel 中
for i in range(2,length+2):
		sheet['A%d'%i] = lis[i-2]['num']
		sheet['B%d'%i] = lis[i-2]['name']
		sheet['C%d'%i] = lis[i-2]['name2']
		sheet['D%d'%i] = lis[i-2]['manager']
		sheet['E%d'%i] = lis[i-2]['time1']
		sheet['F%d'%i] = lis[i-2]['time2']
print('Done')
excel.save('result.xlsx') # 保存文件

方法2:
打开目标 url,按下 F12进入开发者模式,选择 Network,选择 XHR,在这里插入图片描述
然后点击下一页,可以看到 XHR 下面会出现新的返回,点击 Name 下的数据,如图
在这里插入图片描述
对该返回结果的信息分析在右侧,我们对他的 Headers 依次分析:
Request URL:该数据的实际请求 URL,可以看出 URL 中带参数rand,page,size,刚好和我们的实际网页上的信息符合(第一页,每页显示20条信息,rand 为随机数,为了防止浏览器读取缓存而不改变页面)。
Request Method:该数据的请求方法,为 Post,我们待会构造的请求 URL 方法需要与该方法保持一致。
Status Code:状态码,为 200 表示成功,服务器已成功处理了请求。
Request Headers:请求头,用来说明服务器要使用的附加信息。我们构造的爬虫的请求头可以与该请求头保持一致。
X-Requested-With:XMLHttpRequest,请求头中的信息,该信息表明次请求是 Ajax 请求。
Query String Parameters:URL 中所携带的提交的参数,可以看到与 Request URL 是对应的。我们可以构造一个字典,然后使用 urlencode 方法将这些参数写到 URL 中。
Request Payload:ajax 中所 post 的参数,该示例中为空字典,若是有相应的参数,我们可以构造对应的字典,然后转换成 json 格式的数据,再用 post 方法提交。

分析完 Headers,我们再来分析该请求所返回的结果,点击 Headers 右边的 Preview(浏览器帮我们对json格式做了解析),
在这里插入图片描述
可以看到,返回的是一个 Json 格式数据,包含了 content,size,totalPages 等信息,我们所需要的信息应该是在 content 中,我们再层层点开,如下:
在这里插入图片描述
发现 content 中包含了 20 条信息,正是页面上所显示的20条信息,点击第一条具体分析下,发现每条信息又包含了 建立日期(时间戳格式,需自己转换成日期格式,可用 time 库或者 datetime 库),基金名称…工作状态等,这些信息正是我们所想要爬取的信息。

分析完毕,我们来构造函数去请求该 url,代码如下:

from urllib.parse import urlencode
import requests
import json
import datetime
base_url = 'http://gs.amac.org.cn/amac-infodisc/api/pof/fund?'        # 请求 url 所携带参数的前面部分
fund_base_url = 'http://gs.amac.org.cn/amac-infodisc/res/pof/fund/'   # 基金 url 前面的部分
lis_json = []                                                              # 存放 json 数据

headers = {                                                      # 请求头
	'Accept': 'application/json, text/javascript, */*; q=0.01',
	'Accept-Encoding': 'gzip, deflate',
	'Accept-Language': 'zh-CN,zh;q=0.9',
	'Cache-Control':'max-age=0',
	'Connection': 'keep-alive',
	'Content-Length': '2',
	'Content-Type': 'application/json',
	'Host': 'gs.amac.org.cn',
	'Origin': 'http://gs.amac.org.cn',
	'Referer': 'http://gs.amac.org.cn/amac-infodisc/res/pof/fund/index.html',
	'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36',
	'X-Requested-With': 'XMLHttpRequest'
}

def get_page(page):
    '''爬取第xx页信息'''
    # url 携带参数,设置了每页显示 100 条信息
    params = {                                                  
        'rand': 0.3248183083707361,
        'page': page,
        'size': 100,
    }
    url = base_url + urlencode(params)
    try:
        r = requests.post(url,headers=headers,data=json.dumps({}))      # post 方法,将 Request Payload 的信息转换成 json 格式然后提交
        if r.status_code == 200:
            return r.json()
    except requests.ConnectionError as e:
        print('Error',e.args)

def parse_page(r_json):
    if r_json:
        items = r_json.get('content')
        for item in items:
            info = {}
            info['基金名称'] = item.get('fundName')
            info['私募基金管理人名称'] = item.get('managerName')
            info['托管人名称'] = item.get('mandatorName')
            establishDate = item.get('establishDate')
            info['成立时间'] = str(datetime.datetime.fromtimestamp(establishDate/1000).date()) if establishDate else ''       # 成立时间有可能为空,防止这种情况而报错
            putOnRecordDate = item.get('putOnRecordDate')
            info['备案时间'] = str(datetime.datetime.fromtimestamp(putOnRecordDate/1000).date()) if putOnRecordDate else ''
            info['基金链接'] = fund_base_url + item.get('url')
            yield info

def write_to_json(lis):
    with open('info.json','w',encoding='utf-8') as f:
        json.dump({'info':lis},f,ensure_ascii=False)
        
def main():
    for page in range(1,100):
        r_json = get_page(page)
        results = parse_page(r_json)
        for result in results:
            lis_json.append(result)
    write_to_json(lis_json)

if __name__ == '__main__':
    main()

当然,Selenium比较慢,分析Ajxa 接口参数比Selenium快,但是需要花时间在接口参数的分析上(带加密参数时更费事),下期介绍更快的方法:Scrapy 框架!https://blog.csdn.net/luckycdy/article/details/84396587

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,您想要了解如何使用 Python 爬取智联招聘网站上的工作岗位信息对吗? 首先,我们可以使用 Python 中的 requests 库来向智联招聘网站发送 HTTP 请求,从而获取页面内容。然后,我们可以使用 BeautifulSoup 库来解析页面内容,提取出我们需要的信息。 以下是一个示例代码,用于爬取智联招聘网站上的 Python 工程师工作岗位信息: ```python import requests from bs4 import BeautifulSoup url = 'https://fe-api.zhaopin.com/c/i/sou?pageSize=60&cityId=489&salary=0,0&workExperience=-1&education=-1&companyType=-1&employmentType=-1&jobWelfareTag=-1&kw=Python&kt=3&_v=0.97530866&x-zp-page-request-id=ad1b5d3b9e3b4d2d9f0f0e6fcb3f8c1d-1626242840263-285644' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299' } response = requests.get(url, headers=headers) soup = BeautifulSoup(response.content, 'html.parser') job_list = soup.find_all('div', {'class': 'job-list'}) for job in job_list: job_name = job.find('a', {'target': '_blank', 'data-jid': True}).text.strip() job_salary = job.find('span', {'class': 'salary'}).text.strip() job_company = job.find('a', {'class': 'company-name'}).text.strip() job_location = job.find('span', {'class': 'job-area'}).text.strip() job_experience = job.find('span', {'class': 'job-exp'}).text.strip() print(job_name, job_salary, job_company, job_location, job_experience) ``` 在这个示例代码中,我们使用了 requests 库向智联招聘网站发送了一个 HTTP 请求,并设置了请求头部信息,以避免被网站识别为爬虫。然后,我们使用 BeautifulSoup 库解析了页面内容,并从中提取出了工作岗位信息。 您可以根据自己的需求修改代码中的参数和条件,以获得您需要的工作岗位信息。注意,爬取网站信息时要遵守相关法律法规和网站规定,不要过度频繁地请求网站,以免对网站造成影响。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值