爬虫获取微信公众号里面的表格内容+整理数据导出表格
有什么不懂的留言,我看到及时回复;大佬们有更好的方法的话建议一下,互相学习,互相进步,感谢各位!
前言
需求:统计深圳市各大剧场的钢琴表演节目的信息数据
有位朋友,他兼职了某个研究院;给他了一个任务就是统计深圳市内各大剧场的钢琴表演节目信息的数据。这件事情让他头疼,哈哈哈哈 跟我说了以后,我立刻想到用python来解决一下;
我记得,深圳艺文惠公众号 把每周的各大剧场的演出表演总结,并且放到他们的公众号推文里面的。 我平时比较喜欢文艺的东西,没有去过几次,但是常常关注 哈哈哈哈; 现在用上了,这个是我们幸运的点,我们很顺利的找到了数据源(从哪里获取这些数据); 而且这些都是整理好的,直接获取即可。 这里不得不表扬深圳艺文惠公众号,哈哈哈哈;
于是,我打开推文的URL地址,在浏览器中按F12键,打开HTML结构,分析了一波后就有了思路;
思路: 第一步:模拟浏览器请求URL地址 第二步:获取HTML文档结构 第三步:根据HTML结构,定位找到想要的内容 第四步:获取到的内容根据"关键字"筛选数据 第五步:收集每周推文的链接,整理汇总到表格中 第六步:读取推文链接,重复运行上面的五个步骤 第七步:筛选的数据写入到表格中,并且导出
实现
第一步:模拟浏览器请求URL地址
第二步:获取HTML文档结构
Python
import requests # 导入请求库
def getHtml(url):
# 请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE'
}
# 发送GET请求获取网页内容
response = requests.get(url, headers=headers)
response.encoding = 'utf-8'
return response.text # 返回HTML内容
第三步:根据HTML结构,定位找到想要的内容
我们首先分析HMTL结构内容:
从图中可以看到,我们想要获取的数据,在 <table > 面的 <tody >下面的每一个 <tr >里面 因此在 items = doc.xpath('//table//tbody//tr')
中用xpath语法来定位到了我们的所说的每个<tr>
内容,并且把他们存储到items 中
然后我们循环items,获取到每个<tr>
,我们再从每个<tr>
中定位到我们获取到的内容
我们看图片可以得出,我们想要的内容在<tr>
下面的每一项<td>
中
<td>
下面<p>
下面<span>
中有我们想要的那个内容,终于我们获取到了。 因此 text = item.xpath('.//td//p//span//text()')
中定位每个<td>
的<span>
标签; 每个<td>
里面的结构都一样的~
获取到的内容保存text变量中,然后再做一些处理: 有时候获取的内容是空的,因此我们做了判断,有值再添加resData数组中,否则不处理; 循环结束后返回resData数组
但是获取数据后发现了一个问题,获取的数据中大部分情况下:
['深圳音乐厅', '匠心韶华•', '2023', '深圳"一带一路"国际音乐季•永恒的经典', '2023.10.12']
有这种情况,就是数组的第二,三,四项本来是结合为一项的,但是分成了三个部分,因此我们需要纠正这里;
情况紧急因此,我偷懒直接用了巧妙但不恰当的方法来解决了
text[1] += ' '.join(text[2:]) del text[2:]
就是把第二项开始,全部加到一块去;因为日期对本次的需求来说不重要,因此把时间也合集到第二个项里面去,然后删除第二项后的所有项;
Python
from lxml import etree # 导入etree库 用于解析HTML
def getContent(url):
html = getHtml(url) # HTML内容
doc = etree.HTML(html) # 解析HTML内容
items = doc.xpath('//table//tbody//tr')
resData = []
for item in items:
text = item.xpath('.//td//p//span//text()')
if len(text) & len(text) >1:
text[1] += ' '.join(text[2:])
# 删除第二项之后的项
del text[2:]
resData.append(text)
return resData
第四步:获取到的内容根据 关键字筛选数据
遍历数据,查看数据里面是否包含"钢琴"两个字,若包含存入到newData里面,循环完后返回筛选过的数据
Python
def filterData(data):
targetKeywords = '钢琴'
newData = []
for item in data:
if targetKeywords in item[1]:
newData.append(item)
return newData
第五步:收集每周推文的链接,整理汇总到表格中
第六步:读取推文链接,重复运行上面的五个步骤
第七步:筛选的数据写入到表格中,并且导出
Python
# 启动
def run():
# 读取有链接的文件
df = pd.read_excel('11122233.xlsx')
url = df.iloc[:, 1] # 获取表格中的链接
DATA = []
for item in url:
data = getContent(item) # 获取数据
res = filterData(data) #筛选数据
if len(res): # 判断筛选后的数据组,是否有值
DATA= DATA + res # 筛选的数据加起来
if len(DATA):
fileName = str(time.time()) # 时间戳为表格名称,为了避免冲突
df.to_csv(fileName + '.csv', index=False) # 创建表格
# 打开表格并且写入数据
with open(fileName + '.csv', 'w', newline='', encoding='utf-8') as file:
writer = csv.writer(file)
writer.writerows(DATA[1:])
# 调用启动函数
run()
print('--完成--')
这样就完成需求了~ 获取数据->筛选数据->筛选的数据写入到表格中
完整代码片段
Python
import requests
from lxml import etree
import pandas as pd
import csv
import time
# 请求网页获取内容并且返回网页HTML内容
def getHtml(url):
# 请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE'
}
# 发送GET请求获取网页内容
response = requests.get(url, headers=headers)
response.encoding = 'utf-8'
return response.text # 返回HTML内容
# 定为查找内容,并且返回数据
def getContent(url):
html = getHtml(url) # HTML内容
doc = etree.HTML(html) # 解析HTML内容
items = doc.xpath('//table//tbody//tr')
resData = []
for item in items:
text = item.xpath('.//td//p//span//text()')
if len(text) & len(text) >1:
text[1] += ' '.join(text[2:])
# 删除第二项之后的项
del text[2:]
resData.append(text)
return resData
# 根据关键字筛选数据,并且返回筛选后的数据
def filterData(data):
targetKeywords = '钢琴'
newData = []
for item in data:
if targetKeywords in item[1]:
newData.append(item)
return newData
# 启动函数 : 请求->获取数据->筛选数据->写入表格
def run():
# 读取有链接的文件
df = pd.read_excel('11122233.xlsx')
url = df.iloc[:, 1] # 获取表格中的链接
DATA = []
for item in url:
data = getContent(item) # 获取数据
res = filterData(data) # 筛选数据
if len(res): # 判断筛选后的数据组,是否有值
DATA = DATA + res # 筛选的数据加起来
if len(DATA):
fileName = str(time.time()) # 时间戳为表格名称,为了避免冲突
df.to_csv(fileName + '.csv', index=False) # 创建表格
# 打开表格并且写入数据
with open(fileName + '.csv', 'w', newline='', encoding='utf-8') as file:
writer = csv.writer(file)
writer.writerows(DATA[1:])
# 调用启动函数
run()
print('--完成--')