提示:本文爬取深圳市环境水务集团有限公司的公开数据作为数据样例进行数据分析与可视化。
文章目录
一、爬虫
爬虫是一种强大的数据获取工具,可以帮助我们自动化地收集互联网上的各种信息,为数据分析、数据挖掘等领域提供有力的支持。被称为网络爬虫或网页蜘蛛,是一种按照一定规则自动地抓取互联网信息的程序或脚本。Python 爬虫是一种利用 Python 编程语言编写的程序,用于自动地浏览万维网并从网页中提取数据。Python 因其简洁的语法、丰富的库支持和强大的社区支持,成为了实现爬虫项目的热门选择。
基本工作流程:
- 发起请求:通过HTTP库(如Python的requests库)向目标网站发送请求,获取网页内容。
- 获取响应:接收服务器的响应,通常是HTML格式的网页源代码。
- 解析网页:使用解析库(如Python的BeautifulSoup或lxml)对网页内容进行解析,提取出需要的数据(如文本、图片链接、视频链接等)。
- 存储数据:将提取出的数据存储到数据库或文件中,供后续处理或分析使用。
重复以上步骤:根据需要,爬虫可以不断重复上述步骤,以获取更多数据或更新数据
注意事项
- 遵守 robots.txt:在编写爬虫时,请确保遵守目标网站的 robots.txt
文件中的规则,以避免对网站造成不必要的负担或被视为恶意访问。 - 合理设置请求头:为了模拟浏览器访问,你可能需要设置 User-Agent 请求头。
使用代理和延时:为了减少对目标网站服务器的压力,你可以考虑使用代理和设置请求之间的延时。 - 处理 JavaScript 渲染的内容:如果目标网页的内容是通过 JavaScript
动态生成的,那么上述示例中的方法可能无法直接获取到这些内容。这时,你可以考虑使用像 Selenium 这样的工具来模拟浏览器行为。 - 法律和道德问题:在编写爬虫时,请确保你的行为符合当地的法律法规,并尊重网站的版权和隐私政策。
爬虫常用的库
网络请求库
urllib:Python3自带的库,提供了基本的URL请求和网页抓取功能。它是最简单的网络请求库,但功能相对基础。
requests:第三方库,建立在urllib3之上,提供了更加人性化的API。它简化了发送HTTP请求和处理响应的过程,是最常用的Python网络请求库之一。
Selenium:自动化测试工具,通过模拟用户在浏览器中的操作来抓取动态网页内容。它支持多种浏览器,如Chrome、Firefox等,适用于需要JavaScript渲染的页面。
网页解析库
Beautiful Soup:第三方库,用于解析HTML和XML文档。它提供了从网页中提取数据的简便方法,支持多种解析器,如Python标准库中的html.parser和lxml。
lxml:第三方库,支持HTML和XML的解析,并且提供了XPath和CSS选择器的支持。它的解析效率非常高,是处理大型网页数据的理想选择。
pyquery:第三方库,类似于jQuery的Python实现,能够以jQuery的语法来操作解析HTML文档。它对于熟悉jQuery的开发者来说非常友好。
异步及并发库
asyncio:Python标准库(Python 3.4+),提供了异步I/O、时间循环、协同程序和任务等功能。结合aiohttp等异步HTTP库,可以高效地处理大量并发请求。
concurrent.futures:Python标准库,为调用异步执行提供了一个高层次的接口。它支持ThreadPoolExecutor和ProcessPoolExecutor,可以分别用于I/O密集型和CPU密集型任务的并发执行。
aiohttp:基于asyncio实现的HTTP框架,支持异步操作。它提供了与requests类似的API,但具有更高的效率和更好的并发性能。
爬虫框架
Scrapy:一个高级的Web抓取框架,用于从高度复杂的网站中抓取数据。它提供了强大的编码支持、选择器引擎和爬虫引擎,并且支持多种数据库后端和消息队列。Scrapy的学习曲线可能较陡峭,但一旦掌握,可以高效地处理各种爬取任务。
PySpider:一个由国人编写的强大的网络爬虫系统,带有强大的WebUI、脚本编辑器、任务监控器、项目管理以及结果处理器。它支持多种数据库后端和消息队列,并且可以渲染JavaScript页面。
Crawley:一个高速爬取对应网站内容的框架,支持关系和非关系数据库,数据可以导出为JSON、XML等格式。但需要注意的是,Crawley并不是一个广为人知的爬虫框架,可能在使用和社区支持方面存在限制。
其他常用库
fake-useragent:用于生成随机的User-Agent字符串,以模拟不同设备的浏览器请求,有助于绕过一些简单的反爬虫机制。
re:Python标准库,提供了正则表达式的支持。虽然它本身不是爬虫库,但在处理网页数据时经常用于文本匹配和提取。
从深圳市水务局的网站上获取污水处理数据
# -*- codeing = utf-8 -*-
# @Time : 2022/11/29 15:32
# @Author : 小马
# @File: GetData.py
# @Software : PyCharm
#从深圳市水务局获取到深圳各个区的污水处理数据
import urllib.request,urllib.error
import pymysql
import re
from bs4 import BeautifulSoup
import xlwt
findaddress=re.compile(r'<a href="(.*)" target="_blank">20(.*)</a>')
finddataset=re.compile(r'<p style="text-align: center;"><strong>(.*?)</strong></p>')
finddataset2020=re.compile(r'<p style="text-align: left;"><strong>(.*?)</strong></p>')
baseurl="http://swj.sz.gov.cn/xxgk/zfxxgkml/szswgk/tjsj/psgltj/"
#元特区 福田区 罗湖区 盐田区 南山区 宝安区 大鹏新区 龙宝区 龙华区 坪山区 光明区
def ask(url):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36 Core/1.94.178.400 QQBrowser/11.2.5170.400"}
request = urllib.request.Request(url=url, headers=headers)
html = ""
try:
response = urllib.request.urlopen(request)
html = response.read().decode("utf-8")
except urllib.error.URLError as e:
if hasattr(e, "code"): # hasattr() 函数用来判断某个类实例对象是否包含指定名称的属性或方法。
print(e.code)
if hasattr(e, "reason"):
print(e.reason)
return html
def getaddress(baseurl):
addressList=[]
htmll=ask(baseurl)
soup=BeautifulSoup(htmll,"html.parser")
for item in soup("a",target="_blank"):
item=str(item)
add=re.findall(findaddress,item)
if(len(add)>0):
addressList.append(add[0][0])
return addressList
def get2021(): url="http://swj.sz.gov.cn/xxgk/zfxxgkml/szswgk/tjsj/psgltj/content/post_9685824.html"
html=ask(url)
soup=BeautifulSoup(html,"html.parser")
year="2021"
districtList=[]
districtname=[]
sum1=[]
sum2=[]
for i in soup.tbody:
i=str(i)
data=re.findall(finddataset,i)
if(len(data)>0):
if(len(data)==1):
districtname.append(data[0])
if(len(data)==3):
sum1.append(data[1])
sum2.append(data[2])
# for item in soup("p",style="text-align: center"):
# print(item)
# for i in districtname:
# print(i)
# for i in sum1:
# print(i)
# for i in sum2:
# print(i)
for i in range(0,7):
district = []
district.append(year)
district.append(districtname[i])
district.append(sum1[i])
district.append(sum2[i])
districtList.append(district)
return districtList
def get2020(): url="http://swj.sz.gov.cn/xxgk/zfxxgkml/szswgk/tjsj/psgltj/content/post_8666858.html"
html = ask(url)
soup = BeautifulSoup(html, "html.parser")
year = "2020"
districtList = []
districtname = []
sum1 = []
sum2 = []
for i in soup.tbody:
i = str(i)
data = re.findall(finddataset2020, i)
if (len(data) > 0):
if (len(data) == 1):
districtname.append(data[0])
if (len(data) == 3):
sum1.append(data[1])
sum2.append(data[2])
for i in range(0,2):
district = []
district.append(year)
district.append(districtname[i])
district.append(sum1[i])
district.append(sum2[i])
districtList.append(district)
district = []
district.append(year)
district.append("盐田区")
district.append(12)
district.append(3003.25)
districtList.append(district)
for i in range(4,10):
district =