设为首页 收藏本站
查看: 1669|回复: 0

[经验分享] 一个Python小白5个小时爬虫经历

[复制链接]

尚未签到

发表于 2017-6-21 17:00:02 | 显示全部楼层 |阅读模式
前言
  最近业余在做一个基于.NET Core的搜索项目,奈何基层代码写好了,没有看起来很华丽的数据供测试。很巧的也是博客搜索,于是乎想到了博客园。C#也能做做页面数据抓取的,不过在博客园看到的大部分都是python实现,所以就临时想了一下看看python到底是什么东东,不看基础语法,不看语言功能,直接上代码,哪里不会搜哪里。代码完成总共用时大概4个小时,其中搭建环境加安装BeautifulSoup大概1个小时。解析HTML用时间最多了,边看demo边解析,大概2个小时,剩下的时间就是调试加保存数据了。

环境搭建
  既然用python,那么自然少不了语言环境。于是乎到官网下载了3.5版本的。安装完之后,随机选择了一个编辑器叫PyCharm,话说python编辑器还真挺多的。由于本人是小白,所以安装事项不在过多赘述。
DSC0000.png

  建好项目,打开编辑器,直接开工。本来之前用C#写的时候,大体思路就是获取网页内容,然后正则匹配。后来发现网上的帖子也很多。不过在搜索过程中发现,不建议用正则来匹配HTML。有正好我的正则不太好,所以我就搜了一下HTML解析工具,果不其然,人家都做好了,直接拿来用吧。没错就是这个东东:BeautifulSoup 。安装也很简单,不过中间出了个小插曲,就是bs4没有。继续搜,然后需要用pip安装一下就好了。(当然我并不知道ps4和pip是什么鬼)
DSC0001.png


思路分析
  博客吗,我当然就对准了博客园,于是乎,进入博客园首页,查看请求。
DSC0002.png


发送请求
  当然我不知道python是怎么进行网络请求的,其中还有什么2.0和3.0的不同,中间曲曲折折了不少,最终还是写出了最简单的一段请求代码。



import urllib.parse
import urllib.request
# params  CategoryId=808 CategoryType=SiteHome ItemListActionName=PostList PageIndex=3 ParentCategoryId=0 TotalPostCount=4000
def getHtml(url,values):
user_agent='Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36'
headers = {'User-Agent':user_agent}
data = urllib.parse.urlencode(values)
response_result = urllib.request.urlopen(url+'?'+data).read()
html = response_result.decode('utf-8')
return html
#获取数据
def requestCnblogs(index):
print('请求数据')
url = 'http://www.cnblogs.com/mvc/AggSite/PostList.aspx'
value= {
'CategoryId':808,
'CategoryType' : 'SiteHome',
'ItemListActionName' :'PostList',
'PageIndex' : index,
'ParentCategoryId' : 0,
'TotalPostCount' : 4000
}
result = getHtml(url,value)
return result
  其实博客园这个请求还是挺标准的,哈哈正好适合抓取。因为他返回的就是一段html。(如果返回json那不是更好。。。。)

数据解析
  上文已经提到了,用到的是BeautifulSoup,好处就是不用自己写正则,只要根据他的语法来写就好了,在多次的测试之后终于完成了数据的解析。先上一段HTML。然后在对应下面的代码,也许看起来更轻松一些。



<div class="post_item">
<div class="digg">
<div class="diggit" onclick="DiggPost('hyper-xl',6417741,281238,1)">
<span class="diggnum" id="digg_count_6417741">1</span>
</div>
<div class="clear"></div>
<div id="digg_tip_6417741" class="digg_tip"></div>
</div>
<div class="post_item_body">
<h3><a class="titlelnk" href="http://www.cnblogs.com/hyper-xl/p/6417741.html" target="_blank">Python 字符串格式化</a></h3>

<p class="post_item_summary">
<a href="http://www.cnblogs.com/hyper-xl/" target="_blank">
<img width="48" height="48" class="pfs"
src="//pic.cnblogs.com/face/795666/20160421231717.png" alt="" />
</a>    转载请注明出处 Python2.6+ 增加了str.format函数,用来代替原有的'%'操作符
。它使用比'%'更加直观、灵活。下面详细介绍一下它的使用方法。 下面是使用'%'的例子: 格式很像C语言的printf是不是?由于'%'是一个操作符,只能在左右
两边各放一个参数,因此右边多个值需要用元组或 ...
</p>
<div class="post_item_foot">
<a href="http://www.cnblogs.com/hyper-xl/" class="lightblue">新月的力量_141</a>
发布于 2017-02-19 23:07
<span class="article_comment">
<a href="http://www.cnblogs.com/hyper-xl/p/6417741.html#commentform" title="" class="gray">
评论(0)
</a>
</span>
<span class="article_view">
<a href="http://www.cnblogs.com/hyper-xl/p/6417741.html" class="gray">
阅读
(138)
</a>
</span>
</div>
</div>
<div class="clear"></div>
</div>
  通过上文的HTML代码可以看到几点。首先每一条数据都在 div(class="post_item")下。然后 div("post_item_body")下有用户信息,标题,链接,简介等信息。逐一根据样式解析即可。代码如下:



from bs4 import BeautifulSoup
import request
import re
#解析最外层
def blogParser(index):
cnblogs = request.requestCnblogs(index)
soup = BeautifulSoup(cnblogs, 'html.parser')
all_div = soup.find_all('div', attrs={'class': 'post_item_body'}, limit=20)
blogs = []
#循环div获取详细信息
for item in all_div:
blog = analyzeBlog(item)
blogs.append(blog)
return blogs
#解析每一条数据
def analyzeBlog(item):
result = {}
a_title = find_all(item,'a','titlelnk')
if a_title is not None:
# 博客标题
result["title"] = a_title[0].string
# 博客链接
result["href"] = a_title[0]['href']
p_summary = find_all(item,'p','post_item_summary')
if p_summary is not None:
# 简介
result["summary"] = p_summary[0].text
footers = find_all(item,'div','post_item_foot')
footer = footers[0]
# 作者
result["author"] = footer.a.string
# 作者url
result["author_url"] = footer.a['href']
str = footer.text
time = re.findall(r"发布于 .+? .+? ", str)
result["create_time"] = time[0].replace('发布于 ','')
comment_str = find_all(footer,'span','article_comment')[0].a.string
result["comment_num"] = re.search(r'\d+', comment_str).group()
view_str = find_all(footer,'span','article_view')[0].a.string
result["view_num"] = re.search(r'\d+', view_str).group()
return result
def find_all(item,attr,c):
return item.find_all(attr,attrs={'class':c},limit=1)
  上边一堆代码下来,着实花费了我不少时间,边写边调试,边百度~~不过还好最终还是出来了。等数据都整理好之后,然后我把它保存到了txt文件里面,以供其他语言来处理。本来想写个put直接put到ElasticSearch中,奈何没成功。后边在试吧,毕竟我的重点只是导数据,不在抓取这里。



import match
import os
import datetime
import json
def writeToTxt(list_name,file_path):
try:
#这里直接write item 即可,不要自己给序列化在写入,会导致json格式不正确的问题
fp = open(file_path,"w+",encoding='utf-8')
l = len(list_name)
i = 0
fp.write('[')
for item in list_name:
fp.write(item)
if i<l-1:
fp.write(',\n')
i += 1
fp.write(']')
fp.close()
except IOError:
print("fail to open file")
#def getStr(item):
#   return json.dumps(item).replace('\'','\"')+',\n'
def saveBlogs():
for i in range(1,2):
print('request for '+str(i)+'...')
blogs = match.blogParser(i,5)
#保存到文件
path = createFile()
writeToTxt(blogs,path+'/blog_'+ str(i) +'.json')
print('第'+ str(i) +'页已经完成')
return 'success'
def createFile():
date = datetime.datetime.now().strftime('%Y-%m-%d')
path = '/'+date
if os.path.exists(path):
return path
else:
os.mkdir(path)
return path
result = saveBlogs()
print(result)
  上边呢,我取了一百页的数据,也就是大概2000条做测试。

成果验收
  废了好大劲终于写完那些代码之后呢,就可以享受胜利的果实了,虽然是初学者,代码写的很渣,这参考一下,那参考一下,不过还是有些收获的。运行效果如下:
DSC0003.png

  生成的文件:
DSC0004.png

  文件内容:
DSC0005.png


总结
  一个简单的抓取程序就写完了,python还真是TM的好用。以后有空再研究研究吧。代码行数算上空行和注释总共100 (50+25+25) 行。凑个整数好看点~~现在认识字我感觉就可以上手写程序了。这里百度一下,那里google一下,问题就解决了,程序也出来了,大功告成。
  是时候该和python暂时告别了,继续我的.NET事业。话说上次做rss采集的时候,好多“.NET要完蛋了”,“为什么我们不招.NET” 是什么鬼。 小伙伴们,下次见。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-386332-1-1.html 上篇帖子: HTML标签 下篇帖子: 如何查看你的VPS是什么虚拟化架构?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表