您现在的位置是:首页 >技术交流 >港交所ESG报告爬虫记录贴网站首页技术交流

港交所ESG报告爬虫记录贴

Yae Yang 2023-05-23 08:00:01
简介港交所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报告下载的流程结束。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。