爬虫实战 使用python爬取政府公开政策文本
目标:爬取北京市公开发布的所有人才引进相关的政策文本
准备:1、环境Python 3.7,2、使用selenium库中的webdriver,3、安装对应版本的chromedriver
url:在北京市人民政府网站上,人才引进相关政策的url地址是:https://www.beijing.gov.cn/so/s?siteCode=1100000088&tab=zcfg&qt=%E4%BA%BA%E6%89%8D%E5%BC%95%E8%BF%9B
一些参考:(1条消息) Python爬虫(1)一次性搞定Selenium(新版)8种find_element元素定位方式_find_element(by.class_name_轻烟飘荡的博客-CSDN博客
(1条消息) Selenium --- 标签 class及其他属性值更改_selenium修改属性值_Ethel L的博客-CSDN博客
目标网站html内容
在浏览器输入url,可以看见网站的基本内容见下图,我们需要爬取的是图中画线部分:
接下来看一下画线部分的html文本,可以看见每一个政策条目都都在class为'search-result'的div标签里,查看这个div标签,我们可以看见政策的类型,标题,链接等内容。
那么只需要找到所有的class为'search-result'的div标签,然后循环搜索里面的信息(注意a标签里的链接是关键信息,后续需要爬取链接里的具体政策内容),并保存到csv文件中。这里使用的是find_element_XX_XX函数,如果selenium版本比较新,可能这几个函数无法使用了,可以改为使用find_element(By.xx,'xx'),这里需要引入selenium.webdriver.common.by。
解决js渲染的翻页内容
在查看网页的过程中,发现跳转下一页的内容,url并未发生变化,是根据JavaScript动态渲染出的内容,这里就使用find_element找到下一页的按钮然后click它。代码位于29行和44行。
解决搜索位置的切换
还有一个需求是按标题检索含有“人才引进”的政策文本,查看html发现,这两个在交互中能够点击的标签在html中是div标签,一般来说,div标签是无法点击的,并且初步来看这里没有js代码,但是切换搜索位置是全文还是标签,url并没有改变。这也是我比较困惑的地方,如果有了解的大佬可以在评论中解决一下我的疑惑。虽然不太知道这里的原因,但是我发现点击标题,则标题的class变为position-con item-choose item-choose-on,全文的class变为position-con item-choose,点击全文则反过来,那么我们可以执行js代码修改这两个标签的属性,实现搜索位置的切换,代码位于17-21行。
具体代码如下:
1 # -*- coding: utf-8 -*- 2 """ 3 Created on Tue Mar 28 16:46:21 2023 4 5 @author: 6 """ 7 8 from selenium import webdriver 9 import time 10 import pandas as pd 11 from selenium.webdriver.common.by import By 12 13 browser=webdriver.Chrome() 14 browser.get('https://www.beijing.gov.cn/so/s?siteCode=1100000088&tab=zcfg&qt=%E4%BA%BA%E6%89%8D%E5%BC%95%E8%BF%9B') 15 time.sleep(5) 16 17 lable=browser.find_elements(By.CSS_SELECTOR,'.position-con.item-choose')#查找全文和标题的检索项 18 print(lable[0].text,lable[1].text) 19 js= 'arguments[0].setAttribute(arguments[1],arguments[2])' 20 browser.execute_script(js,lable[0],'class','position-con item-choose')#修改全文标签的class 21 browser.execute_script(js,lable[1],'class','position-con item-choose item-choose-on')#修改标题标签的class 22 23 24 time.sleep(2) 25 data=pd.DataFrame([],columns=['类型','链接','标题','文号','发文机构','主题分类','发布日期']) 26 page=1 27 while page: 28 if page !=1: 29 page.click() 30 time.sleep(1) 31 poli=browser.find_elements_by_class_name('search-result') 32 for elements in poli:#一个elements是一个记录 33 p_type=elements.find_element_by_class_name("result-header-lable").text#政策类型 34 link=elements.find_element_by_tag_name("a").get_attribute('href')#链接 35 title=elements.find_element_by_tag_name("a").text#标题 36 table=elements.find_elements_by_class_name("row-content")#文号、发文机构、主题分类、发布日期 37 content=[p_type,link,title] 38 for item in table: 39 content.append(item.text) 40 while len(content)<7: 41 content.append(0) 42 content=pd.DataFrame([content],columns=['类型','链接','标题','文号','发文机构','主题分类','发布日期']) 43 data=pd.concat([data,content]) 44 page=browser.find_element_by_class_name('next') 45 data.to_csv(r'人才政策爬取\北京市人才政策.csv',encoding='utf_8_sig',index=False)
提取政策的具体内容
在上面的代码中,我们实现了爬取所有标题含“人才引进”的政策的大致信息,结果类似下图的表格内容。
接下来需要做的是逐个读取每个政策的链接,将其中的文本内容提取到txt文件中,从html文本中可以看到文本内容均位于id='mainText'的div标签中,每个p标签为一个需要换行的段落。
下面的代码实现了这个过程:
1 # -*- coding: utf-8 -*- 2 """ 3 Created on Tue Mar 28 21:41:39 2023 4 5 @author: 6 """ 7 8 import pandas as pd 9 from selenium import webdriver 10 import time 11 import numpy as np 12 from selenium.webdriver.common.by import By 13 14 files=pd.read_csv(r'人才政策爬取\北京市人才政策.csv',\ 15 encoding='utf-8',header=0) 16 files_link=files[['链接','标题']] 17 files_link=np.array(files_link) 18 files_link=files_link.tolist() 19 print(files_link) 20 browser=webdriver.Chrome() 21 time.sleep(3) 22 for link,title in files_link: 23 with open(r"人才政策爬取\北京市政策文本\\"+title+'.txt',"w") as f: 24 f.write(title+'\n') 25 browser.get(link) 26 time.sleep(1) 27 out_time=browser.find_element_by_xpath("//*[contains(text(),'[发布日期]')]").text 28 f.write(out_time+'\n') 29 content=browser.find_element(By.ID,'mainText') 30 lines=content.find_elements_by_tag_name('p') 31 for line in lines: 32 f.write(line.text+'\n') 33 34