组合拳:利用instant data scraper(精灵球)与selenium/burpsuite爬取联合国立法数据库

最近在从0恶补推荐系统,感觉头发要掉光了。今天早上正美美洗澡呢,突然多了一份“下载资料”的使命。正好鄙人也比较擅长用各种姿势来爬网站,完成任务的同时,尝试采用多种方法,分析比较哪种方法更好,由此来浅浅水一篇博客咯~

 

干活之前先叠甲,感觉爬这个跟爬豆瓣影评没啥区别

网站分析/使用InstantDataScraper获取链接

这就是我们要爬的网站了,网站链接也附上Databases。左边是犯罪立法数据库,右边是判例法数据库。我们直接以立法数据库作为演示,原理都是差不多的。

进入立法数据库,在左边侧边栏可以看到犯罪类别。直接选择网络犯罪即可。可以看到全世界有1560条法律被打上了这个tag。甚至东帝汶和冈比亚都有网络安全相关的立法......作为通辽宇宙的忠实臣子,看到这些熟悉的国名还是有一些亲切的。

分析一下此网站的构成:搜索后通过下拉进行刷新,且信息按照国家进行更新,每个国家下面展示相关的法律。点进去法律之后,会有该法律中与“网络安全”相关的法律被展示,形式也是链接的形式。再点进去,就能看到对应的法条原文了。我们的目的就是把法律名称、所属国家、有关网络安全的法条和法条对应的内容爬取下来。

网站的首页采用下拉式刷新。对于这种情况其实可以写一个response来爬取类ajax请求。但是我们一共也只有300多要爬的数据,也没有更新需求,因此就不搞这么麻烦了。

我们开启instant data scraper。这是一个谷歌插件,在商店里面可以直接下载。其实早些时候一直有自己写一个集成在浏览器里面的爬虫插件的想法,还好没写,这轮子早就存在了哈哈哈哈

打开插件之后可以看到所有的数据都被标黄了。我们选中那个Infinite scroll,点击开始爬取,插件就会帮我们自动滚动了。随后数据都保存在了精灵球里面的面板,包括国家,法律名,链接,真是简单粗暴......

下载csv即可。我对字段进行了一些标注。下一步就是根据法律的链接获取具体法律条文

这是链接里面的样子。继续分析,每一个国家的每一条法律里面有四个字段,分别是重点条款,UNTOC文献,交叉问题,附件。

点入重点条款里面的链接,可以看到我们要爬的数据了。基本上把这些文章以及其对应的标题爬下来就行了,国家作为标签打上去。这样看来,我们需要两次遍历。一次是遍历每个国家的”法律文书“页面,另一次是遍历每本法律的”具体条例“页面。对于这种结构,我们首先果断采取burpsuite爬取。

演示:使用burpsuite进行爬取

burpsuite我就不过多介绍了,担架级别的工具。关于其下载安装和基本使用我之前还写过一篇,有时间也发上来。

在burp内嵌浏览器里面打开“法律文书”页面,找到请求包

发送到repeater,重新请求,可以看到还是能够获得html。

那就简单了。来到intruder,把整个url标记成payload

为了适配请求格式,把前面的东西删掉

大概整理一下,这就是第一次遍历的payload了

粘贴到payload里面

设置资源池,设置三秒爬一次防止封IP,然后就可以开始爬取了。这个网站用规则来找字段比较困难,因为需要的数据没有特定的标签,但是不失为一种很好的路子,因为它不需要写代码~~遇到那种格式鲜明又重复的网站(比如网络招嫖网站之类奇怪的东西)是很好用的。

这里我再展示另一种爬取的方法,就是用python的selenium库

演示:使用selenium进行爬取

上面我们已经用精灵球从首页获得每本法律的对应链接了。这就为我们省了一步,只需要写两个脚本了:

  • 打开法律对应的链接,获取每一章节的链接
  • 打开每一章节的链接,获取法条内容

写爬虫最核心的步骤仍然是对网页进行分析。这里我们先做第一步,获取每一章的链接。随便打开一个法律页面,把网页下载下来用vscode打开,右键选择格式化文档。然后找到我们需要的元素。

看到那个大大的class="cover-parent"和class="leg-article"了吗?前者是a标签的专属class,后者是链接外面text的专属class。bingo,一个白给的结构。我们只需要先批量通过leg-article这个class获得article元素,然后在每个article元素中查询class为cover-parent的元素获取其标签就可以了。

第二步,获取每一章的内容。我们随便打开一章的链接,进入到网页,然后把网站下载,vscode打开,格式化文档,开始分析...

这个网站的格式乱七八糟,找了半天才看到一个小小的topSpace10,ctrl+F发现具有唯一性,下面刚好是要找的内容,妥了... .text就能获取内容了。

下面就是想爬取数据的组织形式了。在爬取第一步的时候能获得国家名、法律名、法条标题、法条链接的内容,第二步的多余信息只有法条的内容。所以我们在第一步可以组织一个json数组,在第二步往每个元素里面加一个content字段就可以了。

再补充一句,对于webdriver我一直觉得用firefox比chrome好,打开很快,而且不用老是更新!chrome没两天就得重下载,老烦人了。

代码也贴到下面。我代码大概写得是一坨屎,看得懂就行吧哈哈哈哈

#第一步的代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import json,tqdm
def save_dict_to_json(data, file_path: str):
    """
    Save a dictionary to a JSON file.

    Args:
    - data (dict): The dictionary to be saved.
    - file_path (str): The path to the JSON file.

    Returns:
    - None
    """
    with open(file_path, 'w', encoding='utf-8') as file:
        json.dump(data, file, ensure_ascii=False, indent=4)

# 初始化WebDriver
driver = webdriver.Firefox(executable_path="D:/softwares/firefoxdriver/geckodriver.exe")  
# 或者使用driver = webdriver.Firefox(),根据您的浏览器选择
# 读取网站列表
res = []
with open('联合国.txt', 'r') as file:
    websites = file.readlines()
# 遍历网站列表
for url in tqdm.tqdm(websites):
    #去空格防止手残
    url = url.strip()
    if not url:
        continue
    try:
        driver.get(url)
        #等待加载完毕
        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'pt-1')))
        # 获取国家名
        country_name = driver.find_element(By.CLASS_NAME, 'pt-1').text
        # 获取法律名
        legislation_name = driver.find_element(By.CLASS_NAME, 'leg-title').text
        # 获取highlighted articles的标题和链接
        highlighted_articles = driver.find_elements(By.CLASS_NAME, 'leg-article')
        highlighted_articles_info = [{'title': article.text,
                                  'link': article.find_element(By.CLASS_NAME,'cover-parent').get_attribute('href')} for article in
                                 highlighted_articles]

        result = {
            'country_name': country_name,
            'legislation_name': legislation_name,
            'highlighted_articles_info': highlighted_articles_info
        }
        res.append(result)
        time.sleep(3)
    except Exception as e:
        print(f"在处理 {url} 时出现错误: {e}")

# 关闭浏览器
driver.quit()
save_dict_to_json(res,'cybelsecurityLaws.json')
#第二步的代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import json,tqdm
def save_dict_to_json(data, file_path: str):
    """
    Save a dictionary to a JSON file.

    Args:
    - data (dict): The dictionary to be saved.
    - file_path (str): The path to the JSON file.

    Returns:
    - None
    """
    with open(file_path, 'w', encoding='utf-8') as file:
        json.dump(data, file, ensure_ascii=False, indent=4)

def read_json_array_to_list(file_path: str):
    """
    Read a JSON file and return its content as a list.

    Args:
    - file_path (str): The path to the JSON file.

    Returns:
    - list: The content of the JSON file as a list.
    """
    with open(file_path, 'r', encoding='utf-8') as file:
        data = json.load(file)
    return data

# 初始化WebDriver
driver = webdriver.Firefox(executable_path="D:/softwares/firefoxdriver/geckodriver.exe")  # 或者使用driver = webdriver.Firefox(),根据您的浏览器选择
# 从txt文件中读取网站列表
res = []
websites = read_json_array_to_list('cybelsecurityLaws.json')
# 遍历网站列表
for i,website in tqdm.tqdm(enumerate(websites)):
    response = website
    # 遍历法律的每个法条
    for i_,article in enumerate(website['highlighted_articles_info']):
        url = article['link']
        if not url:
            continue
        try:
            driver.get(url)
            #等待网站加载完毕
            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'pt-1')))
            #获取网页内容
            content = driver.find_element(By.CLASS_NAME, 'topSpace10').text
            # 网页内容添加到字典中
            response['highlighted_articles_info'][i_]['content'] = content
            time.sleep(5)
        except Exception as e:
            print(f"在处理 {url} 时出现错误: {e}")
    res.append(response)

# 关闭浏览器
driver.quit()
save_dict_to_json(res,'cybelsecurityLaws_detailed.json')

牢骚

爬虫是掌握了很多年的技能了,从大一到大四,使用频率是越来越高,然而一些api还是要现查,不知道是脑子觉得它们无所谓还是怎么样,可能记哪些浩如烟海的api确实没啥用吧。师兄说得对,技术能跑就行,不是拿来炫的。

有道是:

爬虫技艺逐年精,API茫茫似海深。 脑中淡忘非无用,技术运行是本心。

  • 24
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值