因为要分析一个问题,手头上没有数据,在相关网站上找到后,发现要一个一个的点,正好使用Python来爬取并解析数据,获得相应的数据。
在互联网时代,个人获得公开的数据,并做一些分析和验证是值得肯定的。
考虑到业务分析以及技术实现角度,本次主要是涉及数据的爬取,后续的数据预处理以及分析,本文未做介绍。
代码示例
# !/usr/bin/python
# -*- coding:utf-8 -*-
# python3.7
""" 爬取网站和解析数据和存储数据"""
import requests
from bs4 import BeautifulSoup
import time
import pandas as pd
def joinURL(urlBase,urlNew,keepflag=False):
"""拼接url"""
daw= urlBase.split('/') # /2019/index.html
laststring = daw[-1].split('.')
baselist = daw[0:len(daw)-1]
if keepflag == False:
resulturl = "/".join(baselist)+'/'+urlNew # /2019/happy.html
else:
resulturl = "/".join(baselist) + '/' +laststring[0] +'/'+ urlNew # /2019/index/happy.html
return(resulturl)
def getHtml(url,timeout=20, encodingtype='utf-8'):
"""爬取网址 """
try:
headers = {
'Accept-Language': 'zh-cn',
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'Chrome/22.0.1207.1',
}
# 返回respond 对象
respdata = requests.get(url, headers=headers, timeout=timeout)
# 根据文本的编码格式设置文本的形式
print(respdata.encoding)
respdata.encoding = encodingtype
html = respdata.text
respdata.close()
# 返回
return html
except Exception:
print("NO connect")
print(respdata.status_code)
return None
def parseURLData(rawurl,levelkey,levefather):
"""解析HTML中的数据,并和之前的数据存储在一起,rawurl是原始的URL
返回解析的数据urlLinkData 以及下一层的URL-DataUrl2
"""
# 设定数据结构用来存储数据
findata_list = []
# 程序将在这里暂时三秒,爬虫不要给网站造成负担
time.sleep(0.2)
content = nationStatis.getHtml(rawurl,timeout=80,encodingtype='GBK')
soup = BeautifulSoup(content, "html.parser")
urlstart = soup.findAll("tr", {"class":levelkey})
print("#######是否有标签,标签是否有所需要的属性 urlstart.attrs")
for dataname in urlstart:
# ataname.get_text将html所有标签都清除,返回一个只包含文字的字符串
# 通过参数指定tag的文本内容的分隔符
for mytag in dataname.find_all(True):
print(mytag.name)
if mytag.name=='a':
urlLinkLevel = mytag.get("href")
if urlLinkLevel is not None:
DataUrl2 = joinURL(rawurl, urlLinkLevel, keepflag=False)
else:
DataUrl2=''
else:
DataUrl2 = ''
urlLinkData = dataname.get_text(',')
# 不确定某个属性是否存在时,用 tag.get('attr') 方法去获取,没有会返回None
tmp = (levefather,urlLinkData,DataUrl2)
print(tmp)
findata_list.append(tmp)
return findata_list
def text_save(filename, data):
"""写入数据,filename为写入CSV文件的路径,data为要写入数据列表"""
with open(filename, mode='w', encoding='utf-8') as fileobj:
for i in range(len(data)):
s = str(data[i]).replace('(','').replace(')','')#去除[],这两行按数据不同,可以选择
# s = s.replace("'",'').replace(',','') +'\n' #去除单引号,逗号,每行末尾追加换行符
s = s.replace("'",'') +'\n' #去除单引号,逗号,每行末尾追加换行符
print(s)
fileobj.write(s)
print("保存文件成功")
def urlFromtext(inpputfile,outFileDF):
# 读取txt文件数据形式: 感动,每一天,http://www.***u.com/2019/happy.html
interaldata = pd.read_csv(inpputfile, header=None, sep=',', low_memory=False)
# 过滤无效数据
filtdata = interaldata.dropna()
print(filtdata.head())
# 查看数据框的行数
print(filtdata.index.size)
# 只采集含有关键字的数据-针对某一列
bool = filtdata.iloc[:,0].str.contains('感动')
filter_data = filtdata[bool]
print(filter_data)
print(filter_data.index.size)
for index, row in filter_data.iterrows():
# urldata= row.iloc[2].trim()
urldata= row.iloc[2]
levelname ='citytr'
tmp2= (row.iloc[1],row.iloc[0])
Datalist = parseURLData(urldata,levelname,tmp2)
Datalist.to_csv(outFileDF, index=False, mode='a',header=False)
if __name__ == "__main__":
rawUrl = '**********/32.html'
levelKey = "citytr"
# 解析的数据存储
resultURL = parseURLData(rawUrl, levelKey, "每一天")
filenameDF = "D:\\Coding\\Python\urlDF.txt"
text_save(filenameDF,resultURL)
后续
还有一些技术上的问题,记下来,作为
01.HTML网页的缓存技术
02.URL的去重等
03.并行爬取的技术-多进程线程爬虫
04.回调函数的一些应用
05.lxml的解析方式
06.中断与恢复的情况
一些总结点
在对数据的输入-all input is bad until proven otherwise.
对输入做检查,对返回值的一些情况做预估,并做好防御性编程