您现在的位置是:首页 >技术交流 >港交所ESG报告爬虫记录贴网站首页技术交流
港交所ESG报告爬虫记录贴
Part1:按企业代码进行搜索
按一般思路(比如我之前爬虫上交所和深交所的CSR报告),是设定时间,然后直接进行搜索,设置页面的一些参数,或者获得页数和条目数再一页页去爬虫。
但是港交所比较特别,设置年份之后搜索,提示“年份跨度大,需要按照企业代码进行搜索”,于是我按照港交所提供的代码表写了爬虫一个个去搜索(设置payload),代码如下:
import requests
import re
from lxml import etree
import time
# 加载STK code
with open(r"HK-listed firms code_int.txt",'r',encoding='utf-8') as f:
code_list = f.readlines()
url = 'https://www1.hkexnews.hk/search/titlesearch.xhtml?lang=en'
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 OPR/84.0.4316.21",
"cookie": "",
}
def Sprawl(payload):
html = requests.post(url,headers=headers,data=payload,timeout=10)
# print(html.text)
tree = etree.HTML(html.content)
total = tree.xpath('//*[@id="recordCountPanel"]/div/div[1]/text()')[0]
total_num = int(re.sub("D","",total))
print(total_num)
if total_num != 0:
row_list = []
for i in range(1,total_num+1):
row = []
table = tree.xpath('//*[@id="titleSearchResultPanel"]//table[@class="table sticky-header-table table-scroll table-mobile-list"]/tbody/tr['+str(i)+']')[0]
time = table.xpath('./td[1]//text()')[-1]
code = table.xpath('./td[2]//text()')[-1]
STK_name = table.xpath('./td[3]//text()')[-1]
document_name = table.xpath('./td[4]/div[2]/a/text()')[0].replace(' ','').replace('
','').replace(' ','')
document_url = table.xpath('./td[4]/div[2]/a/@href')[0]
row.append(time)
row.append(code)
row.append(STK_name)
row.append(document_name)
row.append(document_url)
# print(row)
row_list.append(row)
print(row_list)
else:
row_list = ''
return row_list
if __name__ == "__main__":
# lists = []
for k in code_list:
print(k)
payload = {
"lang": "EN",
"market": "SEHK",
"searchType": 1,
"t1code": 40000,
"t2Gcode": -2,
"t2code": 40400,
"stockId": int(k.strip()),
"from": 20070625,
"to": 20230412,
"category": 0,
}
row_list = Sprawl(payload)
# lists.extend(row_list)
# time.sleep(2)
with open('log.text','a',encoding='utf-8') as fp:
fp.write(str(row_list)+'
')
这个代码非常常规,就是post请求,设置参数StockId进行遍历爬取就行。不过需要注意的是,遇到一个经常碰到的问题,就是xpath竟然解析不到东西(list out range报错)。在网上搜了一下,发现是因为浏览器显示的xpath是浏览器渲染过的,不一定与网页源码对应。于是我自己仔细看了一下源码的结构,自行构造了想爬虫的元素的xpath。
最后我把爬到的东西写进日志(log.txt),防止程序中断丢失进度,同时这个日志也可以用于后续整理ESG报告的下载网址、发布情况等等。
但是,在运行中,我发现一个很悲伤的事实,那就是,payload参数里面的StockId,它不是和企业的StockCode对应的!而我看了半天也没找到StockCode和StockId的对应规律。于是我又想到下面的方法。
Part2:按年份进行搜索
这个思路想到之后就是实践,而实践表明这是相当可行的。加载出来的页面是一个年度中所有相关条目。而经过解析,我发现页面信息是存储在一个json文件中的,更方便爬取和编录。代码略去,json文件爬取操作为最基础的get请求,只需要在url中改变日期和rowrange就可以控制年份和显示的条目数。
爬取的json文件,我又整理成了excel文件,最后在excel中筛选一下,就可以根据最后得到的下载网址get请求下载了。代码如下:
with open("ESG_url.txt",'r',encoding='utf-8') as fp1:
url_list = fp1.readlines()
with open("ESG_document_name.txt",'r',encoding='utf-8') as fp2:
name_list = fp2.readlines()
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 OPR/84.0.4316.21",
"cookie": "",
}
for url,name in zip(url_list,name_list):
html = requests.get("https://www1.hkexnews.hk/"+url.strip(),headers=headers)
with open("./HK_ESG_report/"+name.replace('
','')+'.pdf','wb') as ff:
ff.write(html.content)
print(name.strip())
这个代码中需要注意的是,同时迭代两个列表,需要用zip(list1, list2)的方式。另外就是二进制写入pdf文件。
至此,港交所ESG报告下载的流程结束。