查看原文
其他

玩转Python之“手把手”教你爬数据(二)

数据分析团队 Stata and Python数据分析 2022-03-15

本文作者:钱梦璇

文字编辑:余术玲

技术总编:张   邯


在上篇文章中,小编已经带领大家通过一级爬虫获得了多彩投网站的项目信息。今天,我们继续学习项目中个人信息的爬取方法,并利用循环获得97页内的所有信息以及实现最终函数的封装。


一.获取单个项目的发起团队信息(二级爬虫)

打开网页https://www.duocaitou.com/project/detail/NHdWaS81RHRueGs9,对应第一页的第一个项目信息。运用同样的方法,进入开发者模式,可以找到所需信息的真实链接getProjectSummary,它的Response中“projectTeamList”键对应了第一个项目(宿舍·北京鼓韵国际青年旅舍)的发起团队信息(只截取一部分)。如下所示:



此时点击Response旁的Headers,找到其请求头(Request headers)和Payload报文,如下图所示:

 


运用和上述程序相同的方法,获取这个项目的发起团队中每个人的信息,具体程序如下:

url="https://pcapi.duocaitou.com/pc/project/getProjectSummary"headers={"Accept": "application/json,text/plain, */*", "Content-Type": "application/json;charset=UTF-8", "Referer":"https://www.duocaitou.com/project/detail/NHdWaS81RHRueGs9", "Sec-Fetch-Mode": "cors", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" }data = {"id":"NHdWaS81RHRueGs9"} #此项目对应的idreq=json.loads(requests.post(url,headers=headers,data=json.dumps(data)).text)["data"]["projectTeamList"]print(req)

这时得到上图 “projectTeamList”对应的此发起团队中每个人的详细信息。结果如下所示:

 

二.主程序

主程序是整个程序运行开始的地方,也是整个程序的核心。首先是将变量名导入一个csv文件中:
if __name__ =="__main__": #主程序 Varname=["imageS","endDate","initiator","imageM","initiatorLogo","title","financingRate","preheatdateEnd","investUpMoney","remainDays","payType","projectProgress","investFinancingRate","pType","raise","statusName","id","address","launch","upMoney","financingType","financingMoney","pjtBreif","finishDate","investmentType","status","brief","picUrl","name","logo","Person_id","sort","content"]with open("E:\\多彩投.csv","w",encoding="gb18030")as f:        f.write("\t".join(Varname)+"\n")
从上述分析得到的两种信息中,我们发现有一些固定的变量名,即项目信息对应的变量名有:"imageS","endDate","initiator","imageM","initiatorLogo","title","financingRate","preheatdateEnd"等;个人信息对应的变量名有:"brief","picUrl","name","logo","id","sort","content"。注意到这两类信息有一个相同的变量名为“id”,为了区别开来,我们将个人信息对应的“id”变量名改为“Person_id”。如上所示,设置一个包含所有变量名的列表Varname。
利用open()函数返回“E://多彩投.csv”路径下的一个csv文件,其中“w”表示仅写入(将删除同名的现有文件),编码格式为"gb18030"。这里的 f.write()函数将相应内容写入到csv文件中,其中,“\t”是水平制表符,将每个变量名用tab键分隔开;将所有变量名都输入进去后,最后用“\n”来换行来方便之后向文件中输入内容。
 
接下来,利用循环获取信息:
for i in range(1,98): ProjectInfo=(GetSinglePage(i)) for EachProject in ProjectInfo: PersonInfo=(GetSingleProject(EachProject["id"])) for EachPerson in PersonInfo:                         Json2csv("E:\\多彩投.csv",EachProject,EachPerson)
其中,第一层循环是对页数i进行循环,不同的i对应不同页数的项目信息ProjectInfo;第二层循环是对每一页项目信息ProjectInfo中的每个项目EachProject进行循环,为了获取每个项目的具体信息;第三层循环是对每个发起团队信息PersonInfo中的每个人EachPerson进行循环,为了获得每个项目对应的每个人的具体信息。
 
GetSinglePage(i)和GetSingleProject(EachProject["id"])分别对应的是为了封装一级爬虫和二级爬虫而定义的函数,将EachProject字典中“id”键对应的值作为GetSingleProject()函数对应的参数,这样可以将每个项目和其团队的信息一一对应起来。上述介绍只爬取了第一页和第一个项目的详细信息,我们需要通过这两个函数将每一页项目和每个人的信息爬取出来(见最终程序)。获取信息的方式是通过定义Json2csv()这个函数(见最终程序),将得到的信息传入到csv文件中。


三.信息的获取与导入


由于篇幅限制,在此仅解释将项目信息导入csv文件的方法。open()函数打开“多彩投.csv”文件,与上述“w”模式不同,“a”表示打开文件进行追加。定义一个空列表tempInfo,通过循环不断地其输入信息,并利用f.write()函数将tempInfo写入到csv中。
with open("E://多彩投.csv","a",encoding= "gb18030") as f: tempInfo= []for EachVar in Project_VarName: # Project_VarName表示项目信息对应的变量名列表 if EachVar in ProjectInfo: #根据if条件语句进行判断            tempInfo.append(str(ProjectInfo[EachVar]).replace("\n","").replace("\t","").replace("\r","")) else:            tempInfo.append("")tempInfo ="\t".join(tempInfo)+"\n"print(tempInfo)f.write(tempInfo)
分析if条件语句,对于Project_VarName中的每一个变量EachVar,如果它出现在ProjectInfo中,那么就向tempInfo中输入这个变量对应的信息,否则不添加。由于一些变量(如id、sort)对应的信息不是字符串,故需要将所有信息都转化为字符串格式,另外,还有一些变量对应的信息中含有回车,换行等符号(“\r”是回车,“\n”是换行),我们利用字符串的replace方法将这些符号都替换为空。同理,再利用循环和if条件语句将个人信息依次输入文件(见最终程序)。


四.最终程序和结果

我们通过实现函数的封装,然后来调用函数。最终整理得到的程序如下所示:
import requestsimport json def GetSinglePage(i): #用函数将一级爬虫封装起来 url="https://pcapi.duocaitou.com/pc/project/goProject" headers={"Accept":"application/json, text/plain, */*", "Content-Type": "application/json;charset=UTF-8", "Referer":"https://www.duocaitou.com/project?pageNum=1", "Sec-Fetch-Mode":"cors", "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, likeGecko) Chrome/76.0.3809.100 Safari/537.36" } data={"pageNum":str(i), "pageSize": "9"} #不同的i对应不同的页数 return json.loads(requests.post(url,headers=headers,data=json.dumps(data)).text)["data"]["list"] def GetSingleProject(id): #用函数将二级爬虫封装起来 url="https://pcapi.duocaitou.com/pc/project/getProjectSummary" headers={"Accept":"application/json, text/plain, */*", "Content-Type":"application/json;charset=UTF-8", "Referer":"https://www.duocaitou.com/project/detail/NHdWaS81RHRueGs9", "Sec-Fetch-Mode": "cors", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" } data= {"id":id} #不同的项目对应不同的id return json.loads(requests.post(url,headers=headers,data=json.dumps(data)).text)["data"]["projectTeamList"] def Json2csv(FileName,ProjectInfo,PersonInfo): #将输入信息的程序用函数封装起来 Project_VarName=["imageS","endDate","initiator","imageM","initiatorLogo","title","financingRate","preheatdateEnd","investUpMoney","remainDays","payType","projectProgress","investFinancingRate","pType","raise","statusName","id","address","launch","upMoney","financingType","financingMoney","pjtBreif","finishDate","investmentType","status"] Person_VarName=["brief","picUrl","name","logo","id","sort","content"] with open(FileName,"a",encoding = "gb18030") as f: tempInfo= [] for EachVar in Project_VarName: #输入项目信息 if EachVar in ProjectInfo: tempInfo.append(str(ProjectInfo[EachVar]).replace("\n","").replace("\t","").replace("\r","")) else: tempInfo.append("") for EachVar in Person_VarName: #输入个人信息 if EachVar in PersonInfo: tempInfo.append(str(PersonInfo[EachVar]).replace("\n","").replace("\t","").replace("\r","")) else: tempInfo.append("") tempInfo= "\t".join(tempInfo)+"\n" print(tempInfo) f.write(tempInfo)if __name__ == "__main__": #主程序 Varname=["imageS","endDate","initiator","imageM","initiatorLogo","title","financingRate","preheatdateEnd","investUpMoney","remainDays","payType","projectProgress","investFinancingRate","pType","raise","statusName","id","address","launch","upMoney","financingType","financingMoney","pjtBreif","finishDate","investmentType","status","brief","picUrl","name","logo","Person_id","sort","content"]with open("E:\\多彩投.csv","w",encoding="gb18030") as f: f.write("\t".join(Varname)+"\n")for i in range(1,98): ProjectInfo=(GetSinglePage(i)) for EachProject in ProjectInfo: PersonInfo=(GetSingleProject(EachProject["id"])) for EachPerson in PersonInfo: Json2csv("E:\\多彩投.csv",EachProject,EachPerson)
结果如下所示(只截取了其中一个项目对应的发起团队信息):



多彩投网页中的所有项目以及对应的发起团队的信息就得到啦,并且都保存在了"E://多彩投.csv"路径下,大家赶快动手操作一下吧~

 

对我们的推文累计打赏超过1000元,我们即可给您开具发票,发票类别为“咨询费”。用心做事,不负您的支持!
往期推文推荐

       玩转Python之“手把手”教你爬数据(一)

labelsof和labelbook介绍
Statalist上的“火云邪神”
爬虫实战程序的函数封装
Zipfile(二)
利用collapse命令转化原始数据
Stata中的数值型
爬虫实战——聚募网股权众筹信息爬取
duplicates drop之前,我们要做什么?
类型内置函数-type() isinstance()
数据含义记不住?—— label“大神”来帮忙

实战演练-如何获取众筹项目的团队信息

Zipfile(一)

tabplot命令

Jupyter Notebook不为人知的秘密

字符串方法(三)

encode 和decode——带你探索编码与解码的世界

字符串方法(二)

如何快速生成分组变量?


关于我们

微信公众号“Stata and Python数据分析”分享实用的stata、python等软件的数据处理知识,欢迎转载、打赏。我们是由李春涛教授领导下的研究生及本科生组成的大数据处理和分析团队。

此外,欢迎大家踊跃投稿,介绍一些关于stata和python的数据处理和分析技巧。
投稿邮箱:statatraining@163.com
投稿要求:
1)必须原创,禁止抄袭;
2)必须准确,详细,有例子,有截图;
注意事项:
1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。
2)邮件请注明投稿,邮件名称为“投稿+推文名称”。
3)应广大读者要求,现开通有偿问答服务,如果大家遇到有关数据处理、分析等问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存