基于selenium和bs4的通用数据采集技术(附代码)

AI应用开发相关目录

本专栏包括AI应用开发相关内容分享,包括不限于AI算法部署实施细节、AI应用后端分析服务相关概念及开发技巧、AI应用后端应用服务相关概念及开发技巧、AI应用前端实现路径及开发技巧
适用于具备一定算法及Python使用基础的人群

  1. AI应用开发流程概述
  2. Visual Studio Code及Remote Development插件远程开发
  3. git开源项目的一些问题及镜像解决办法
  4. python实现UDP报文通信
  5. python实现日志生成及定期清理
  6. Linux终端命令Screen常见用法
  7. python实现redis数据存储
  8. python字符串转字典
  9. python实现文本向量化及文本相似度计算
  10. python对MySQL数据的常见使用
  11. 一文总结python的异常数据处理示例
  12. 基于selenium和bs4的通用数据采集技术(附代码)


一、前言

本文所说的数据采集技术即爬虫,爬虫技术用于从互联网上抓取大量数据。这些爬虫程序能够自动化地访问网页/公众号平台、解析内容,并提取所需的信息。在大数据和机器学习等领域,爬虫技术发挥着至关重要的作用。

数据采集技术为项目提供丰富的数据资源,根据这些信息进行产品设计和创新,持续改进和优化产品。

二、环境配置

pip install beautifulsoup4

pip install selenium

安装WebDriver:Selenium需要WebDriver来与浏览器进行交互。不同的浏览器需要不同的WebDriver。例如,如果你使用的是Chrome浏览器,你需要下载并安装chromedriver;如果你使用的是Firefox浏览器,你需要下载并安装geckodriver。请根据你的浏览器类型,从官方网站或相关源下载对应的WebDriver,并将其放置在系统路径下,以便Selenium能够找到并调用它。

在这里插入图片描述

三、技术策略

http://ytzwfw.sd.gov.cn/yt/icity/project/index

在这里插入图片描述
特性1:翻页后url无变化规律
在这里插入图片描述
特性2:数据爬取分为2阶段,需要在url后再爬取具体数据项的url_son,再针对url_son设计程序采集。

在这里插入图片描述
在这里插入图片描述

特性3:html源码中无法直接获取数据存在形式,仅开发者模式下才能观察到

由此可知该网站具备相当程度的反扒设计。

策略:
设计两个阶段的数据采集程序,克服特点2
采取selenium自动化框架,克服特点1
采取bs4数据采集框架,客服特点3

四、代码实例

step1:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
import time
def get_single_page_data():
    result = []
    for i in range(10):
        try:
            mid_title = driver.find_element(By.XPATH, '//*[@id="itemlist"]/div[' + str(i + 1) + ']/div[1]/a[1]').text
            mid_url = driver.find_element(By.XPATH, '//*[@id="itemlist"]/div[' + str(i + 1) + ']/div[1]/a[1]').get_attribute('onclick')
            mid = [mid_title,mid_title,mid_url.split("'")[-2]]
            # print(mid)
            result.append(mid)
        except:
            print('data error!')
    return result

def write_data_totxt(data:str):
    with open('data.txt', 'a') as f:
        f.write(data)
        f.write('\n')

# 创建一个Chrome浏览器实例
driver = webdriver.Chrome(options=Options(), executable_path=r'C:\Program Files\Google\Chrome\Application\chromedriver.exe')
# 打开目标网页
driver.get("http://ytzwfw.sd.gov.cn/yt/icity/project/index")


data = []
page = 0
while page<= 628:  # 循环页数
    try:
        single_page_data = get_single_page_data() # 抓数据
        for i in single_page_data:
            print(i)
            write_data_totxt(i[0])
            write_data_totxt(i[-1])
        #     /html/body/div[5]/div/div/div[2]/div/a[8]
        driver.find_element(By.CLASS_NAME, 'laypage_next').click() # 翻页
        time.sleep(2)
        page += 1
    except:
        print('page error!')

driver.quit()

爬取结果如下所示:

在这里插入图片描述

step2:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
import requests
from bs4 import BeautifulSoup


def get_end_time(url):
    options = webdriver.ChromeOptions()
    # 添加无头模式选项
    options.add_argument("--headless")
    # 创建一个Chrome浏览器实例
    driver = webdriver.Chrome(options=options, executable_path=r'C:\Program Files\Google\Chrome\Application\chromedriver.exe')
    # 打开目标网页
    driver.get(url)
    goal = driver.find_element(By.CLASS_NAME, 'law-time').text
    driver.quit()

    return goal


def getHTMLText(url, timeout=30):
    try:
        r = requests.get(url, timeout=30)  # 用requests抓取网页信息
        r.raise_for_status()  # 可以让程序产生异常时停止程序
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return '产生异常'


def collapse_spaces(s):
    while "  " in s:
        s = s.replace("  ", " ")
    return s


def get_single_data(name: str, url: str, data) -> dict:
    html = getHTMLText(url)
    soup = BeautifulSoup(html, 'html.parser')  # 用BeautifulSoup库解析网页
    temps_div = soup.find_all('div', attrs={'class': "table-table"})

    raw_content_ls = temps_div[0].select('td')
    data[name] = {}
    data[name]['实施主体'] = raw_content_ls[0].text
    data[name]['承办机构'] = raw_content_ls[1].text
    data[name]['事项版本'] = raw_content_ls[4].text
    data[name]['办理结果名称'] = raw_content_ls[6].text.replace('\n', '').replace('\t', '').replace('\r', '').replace(' ', '')
    data[name]['法定办结时限'] = get_end_time(url)
    data[name]['是否存在运行系统'] = temps_div[0].select('td[width="30%"]')[-1].text
    data[name]['咨询渠道'] = collapse_spaces(
        temps_div[0].select('td[colspan="3"]')[-3].text.replace('\r', ' ').replace('\t', ' ').replace('\n', ' '))[1:-1]
    data[name]['投诉渠道'] = collapse_spaces(
        temps_div[0].select('td[colspan="3"]')[-2].text.replace('\r', ' ').replace('\t', ' ').replace('\n', ' '))[1:-1]
    data[name]['受理时间、地点'] = collapse_spaces(
        temps_div[0].select('td[colspan="3"]')[-1].text.replace('\r', ' ').replace('\u2003', ' ').replace('\n',
                                                                                                          ' ').replace(
            '\t', ' '))[1:-1]

    return data

titles = []
url_ends = []
with open('data.txt','r')as f:
    mid = f.readlines()
    for i in range(len(mid)):
        if i %2 == 0:
            titles.append(mid[i].strip('\n'))
        else:
            url_ends.append(mid[i].strip('\n'))
print(titles[:10])
print(url_ends[:10])
print(len(titles),len(url_ends))

data = {}
start_index = 800
for index in range(len(titles[start_index:start_index+400])):
    print(titles[index])
    url = 'http://ytzwfw.sd.gov.cn/yt/icity/proinfo/index4ZS?id={url_end}'.format(url_end=url_ends[index])
    print(url)
    try:
        get_single_data(titles[index],url,data)
        print(data[titles[index]])
    except:
        print('error')
print('爬取完成!')

import json

# 将字典转换为JSON格式的字符串
json_string = json.dumps(data, ensure_ascii=False)

# 将JSON字符串写入文本文件
with open('my_dict2.txt', 'w', encoding='utf-8') as file:
    file.write(json_string)
'''
with open('my_dict.txt', 'r', encoding='utf-8') as file:  
    loaded_dict = json.loads(file.read())  
print(loaded_dict)
'''

爬取结果如下所示:
在这里插入图片描述
如有代码需求,欢迎留言、私信我!

20240328更新

可直接抓取政策项、政策子页、政策分类;应对了政策子页反爬手段。

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
import time
import json

def get_single_page_data(result):
    for i in range(10):
        mid_dict = {
            'title': '',
            'type': '',
            'page': '',
        }
        try:
            folder_flag = driver.find_element(By.XPATH, '//*[@id="itemlist"]/div[' + str(i + 1) + ']').get_attribute('is_load')
            # 含子页
            if folder_flag:
                # //*[@id="itemlist"]/div[9]/a[2]
                mid_type = driver.find_element(By.XPATH, '//*[@id="itemlist"]/div[' + str(i + 1) + ']/a[2]').text
                mid_page = str(i + 1)
                # //*[@id="itemlist"]/div[9]
                code = 'content' + driver.find_element(By.XPATH, '//*[@id="itemlist"]/div[' + str(i + 1) + ']').get_attribute('folder_code')


                for j in range(20):
                    try:
                        mid_dict = {
                            'title': '',
                            'type': '',
                            'page': '',
                        }

                        # //*[@id="content599a1da2-1581-4422-8f90-edbfa009fe5011370600004260520N"]/table/tbody/tr[1]/td[2]/div/a
                        mid_title = driver.find_element(By.XPATH, '//*[@id="' + code + '"]/table/tbody/tr[' + str(j+1) + ']/td[2]/div/a').get_attribute('text')

                        print(mid_title)

                        mid_dict['title'] = mid_title
                        mid_dict['type'] = mid_type
                        mid_dict['page'] = mid_page

                        result.append(mid_dict)
                    except Exception as e:
                        print('son page error.')
                        print(e)
                        break


            # 不含子页
            else:
                # //*[@id="itemlist"]/div[10]/div[1]/a[1]
                # //*[@id="itemlist"]/div[10]/div[1]/a[2]
                mid_title = driver.find_element(By.XPATH, '//*[@id="itemlist"]/div[' + str(i + 1) + ']/div[1]/a[1]').text
                mid_type = driver.find_element(By.XPATH, '//*[@id="itemlist"]/div[' + str(i + 1) + ']/div[1]/a[2]').text
                mid_page = str(i + 1)

                mid_dict['title'] = mid_title
                mid_dict['type'] = mid_type
                mid_dict['page'] = mid_page

                result.append(mid_dict)

        except Exception as e:
            print('page error.')
            print(e)
    return result


def write_data_tojson(data: dict):
    with open('data.json', 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=4)


# 创建一个Chrome浏览器实例
#浏览器启动选项
option=webdriver.ChromeOptions()
#指定为无界面模式
option.add_argument('--headless')
driver = webdriver.Chrome(options=option, executable_path=r'C:\Program Files\Google\Chrome\Application\chromedriver.exe')
# 打开目标网页
driver.get("http://ytzwfw.sd.gov.cn/yt/icity/project/index")


data = []
page = 0

result = []
#while page<= 610:  # 循环页数
while page<= 5:  # 循环页数
    try:
        single_page_data = get_single_page_data(result) # 抓数据
        write_data_tojson(single_page_data)
        #     /html/body/div[5]/div/div/div[2]/div/a[8]
        driver.find_element(By.CLASS_NAME, 'laypage_next').click() # 翻页
        time.sleep(2)
        page += 1
    except:
        print('page error!')

driver.quit()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

写代码的中青年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值