Python爬虫小实践:爬取任意CSDN博客所有文章的文字内容(或可改写为保存其他的元素),间接增加博客访问量 pythonc浏览器
Python并不是我的主业,当初学Python主要是为了学爬虫,以为自己觉得能够从网上爬东西是一件非常神奇又是一件非常有用的事情,因为我们可以获取一些方面的数据或者其他的东西,反正各有用处。
这两天闲着没事,主要是让脑子放松一下就写着爬虫来玩,上一篇初略的使用BeautifulSoup去爬某个CSDN博客的基本统计信息(http://blog.csdn.net/hw140701/article/details/55048364),今天就想要不就直接根据某个CSDN博客的主页的地址爬取该博客的所有文章链接,进而提取每一篇文章中的元素,我这里是提取每一篇博客中的文字信息。
一、主要思路
通过分析CSDN博客的网站源码,我们发现当我们输入某博客主页网址时,如:http://blog.csdn.net/hw140701
在主页会有多篇文章,以及文章的链接,默认的是15篇。在主页博客的底部会有分页的链接,如下图
如图所示,一共65篇分5页,每一页中又包含了15篇文章的链接。
所以我们总体的思路是:
1.输入博客主页地址,先获取当前页所有文章的链接;
2.获取每个分页的链接地址
3.通过每个分页的链接地址获取每一个分页上所有文章的链接地址
4.根据每一篇文章的链接地址,获取每一篇文章的内容,直到该博客所有文章都爬取完毕
二、代码分析
2.1分页链接源码分析
用浏览器打开网页地址,使用开发者工具查看博客主页网站源码,发现分页链接地址隐藏在下列标签之中
所以我们通过下列代码所有分页链接进行匹配
[python] view plain copy
<!--[if !supportLists]-->1. <!--[endif]-->bsObj.findAll("a",href=re.compile("^/([A-Za-z0-9]+)(/article)(/list)(/[0-9]+)*$")):#正则表达式匹配分页的链接
bsObj为BeautifulSoup对象
2.2分页上每一篇文章链接源码分析
得到每一个分页的链接后,对每一个分页上的文章链接源码进行分析,其源码如下
通过分析,所以我们采取以下的方法进行匹配
[python] view plain copy
<!--[if !supportLists]-->1. <!--[endif]-->bsObj.findAll("a",href=re.compile("^/([A-Za-z0-9]+)(/article)(/details)(/[0-9]+)*$"))
或者
[python] view plain copy
<!--[if !supportLists]-->1. <!--[endif]-->bsObj.findAll("span",{"class":"link_title"})
2.3每一篇文章中文字内容源码分析
通过对每一篇文章中的网站源码进行分析,发现其内容位于源码中的以下位置
所以通过下列代码进行匹配
[python] view plain copy
<!--[if !supportLists]-->1. <!--[endif]-->bsObj.findAll("span",style=re.compile("font-size:([0-9]+)px"))
3.全部代码以及结果
现附上全部代码,注释部分可能有错,可以根据此代码自行修改,去爬取某CSDN博客中的任意元素
[python] view plain copy
<!--[if !supportLists]-->1. <!--[endif]-->#__author__ = 'Administrat
<!--[if !supportLists]-->2. <!--[endif]-->#coding=utf-8
<!--[if !supportLists]-->3. <!--[endif]-->import io
<!--[if !supportLists]-->4. <!--[endif]-->import os
<!--[if !supportLists]-->5. <!--[endif]-->import sys
<!--[if !supportLists]-->6. <!--[endif]-->import urllib
<!--[if !supportLists]-->7. <!--[endif]-->from urllib.request import urlopen
<!--[if !supportLists]-->8. <!--[endif]-->from urllib import request
<!--[if !supportLists]-->9. <!--[endif]-->from bs4 import BeautifulSoup
<!--[if !supportLists]-->10. <!--[endif]-->import datetime
<!--[if !supportLists]-->11. <!--[endif]-->import random
<!--[if !supportLists]-->12. <!--[endif]-->import re
<!--[if !supportLists]-->13. <!--[endif]-->import requests
<!--[if !supportLists]-->14. <!--[endif]-->import socket
<!--[if !supportLists]-->15. <!--[endif]-->socket.setdefaulttimeout(5000)#设置全局超时函数
<!--[if !supportLists]-->16. <!--[endif]-->
<!--[if !supportLists]-->17. <!--[endif]-->
<!--[if !supportLists]-->18. <!--[endif]-->sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030')
<!--[if !supportLists]-->19. <!--[endif]-->headers1={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'}
<!--[if !supportLists]-->20. <!--[endif]-->headers2={'User-Agent':'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36'}
<!--[if !supportLists]-->21. <!--[endif]-->headers3={'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11'}
<!--[if !supportLists]-->22. <!--[endif]-->
<!--[if !supportLists]-->23. <!--[endif]-->#得到CSDN博客某一个分页的所有文章的链接
<!--[if !supportLists]-->24. <!--[endif]-->articles=set()
<!--[if !supportLists]-->25. <!--[endif]-->def getArticleLinks(pageUrl):
<!--[if !supportLists]-->26. <!--[endif]--> #设置代理IP
<!--[if !supportLists]-->27. <!--[endif]--> #代理IP可以上http://zhimaruanjian.com/获取
<!--[if !supportLists]-->28. <!--[endif]--> proxy_handler=urllib.request.ProxyHandler({'post':'210.136.17.78:8080'})
<!--[if !supportLists]-->29. <!--[endif]--> proxy_auth_handler=urllib.request.ProxyBasicAuthHandler()
<!--[if !supportLists]-->30. <!--[endif]--> opener = urllib.request.build_opener(urllib.request.HTTPHandler, proxy_handler)
<!--[if !supportLists]-->31. <!--[endif]--> urllib.request.install_opener(opener)
<!--[if !supportLists]-->32. <!--[endif]--> #获取网页信息
<!--[if !supportLists]-->33. <!--[endif]--> req=request.Request(pageUrl,headers=headers1 or headers2 or headers3)
<!--[if !supportLists]-->34. <!--[endif]--> html=urlopen(req)
<!--[if !supportLists]-->35. <!--[endif]--> bsObj=BeautifulSoup(html.read(),"html.parser")
<!--[if !supportLists]-->36. <!--[endif]--> global articles
<!--[if !supportLists]-->37. <!--[endif]--> #return bsObj.findAll("a",href=re.compile("^/([A-Za-z0-9]+)(/article)(/details)(/[0-9]+)*$"))
<!--[if !supportLists]-->38. <!--[endif]--> #return bsObj.findAll("a")
<!--[if !supportLists]-->39. <!--[endif]--> #for articlelist in bsObj.findAll("span",{"class":"link_title"}):
<!--[if !supportLists]-->40. <!--[endif]--> for articlelist in bsObj.findAll("span",{"class":"link_title"}):#正则表达式匹配每一篇文章链接
<!--[if !supportLists]-->41. <!--[endif]--> #print(articlelist)
<!--[if !supportLists]-->42. <!--[endif]--> if 'href' in articlelist.a.attrs:
<!--[if !supportLists]-->43. <!--[endif]--> if articlelist.a.attrs["href"] not in articles:
<!--[if !supportLists]-->44. <!--[endif]--> #遇到了新界面
<!--[if !supportLists]-->45. <!--[endif]--> newArticle=articlelist.a.attrs["href"]
<!--[if !supportLists]-->46. <!--[endif]--> #print(newArticle)
<!--[if !supportLists]-->47. <!--[endif]--> articles.add(newArticle)
<!--[if !supportLists]-->48. <!--[endif]-->#articlelinks=getArticleLinks("http://blog.csdn.net/hw140701")
<!--[if !supportLists]-->49. <!--[endif]-->#for list in articlelinks:
<!--[if !supportLists]-->50. <!--[endif]--> #print(list.attrs["href"])
<!--[if !supportLists]-->51. <!--[endif]--> #print(list.a.attrs["href"])
<!--[if !supportLists]-->52. <!--[endif]-->
<!--[if !supportLists]-->53. <!--[endif]-->#写入文本
<!--[if !supportLists]-->54. <!--[endif]-->#def data_out(data):
<!--[if !supportLists]-->55. <!--[endif]--> # with open("E:/CSDN.txt","a+") as out:
<!--[if !supportLists]-->56. <!--[endif]--> # out.write('\n')
<!--[if !supportLists]-->57. <!--[endif]--> # out.write(data,)
<!--[if !supportLists]-->58. <!--[endif]-->
<!--[if !supportLists]-->59. <!--[endif]-->
<!--[if !supportLists]-->60. <!--[endif]-->#得到CSDN博客每一篇文章的文字内容
<!--[if !supportLists]-->61. <!--[endif]-->def getArticleText(articleUrl):
<!--[if !supportLists]-->62. <!--[endif]--> #设置代理IP
<!--[if !supportLists]-->63. <!--[endif]--> #代理IP可以上http://zhimaruanjian.com/获取
<!--[if !supportLists]-->64. <!--[endif]--> proxy_handler=urllib.request.ProxyHandler({'https':'111.76.129.200:808'})
<!--[if !supportLists]-->65. <!--[endif]--> proxy_auth_handler=urllib.request.ProxyBasicAuthHandler()
<!--[if !supportLists]-->66. <!--[endif]--> opener = urllib.request.build_opener(urllib.request.HTTPHandler, proxy_handler)
<!--[if !supportLists]-->67. <!--[endif]--> urllib.request.install_opener(opener)
<!--[if !supportLists]-->68. <!--[endif]--> #获取网页信息
<!--[if !supportLists]-->69. <!--[endif]--> req=request.Request(articleUrl,headers=headers1 or headers2 or headers3)
<!--[if !supportLists]-->70. <!--[endif]--> html=urlopen(req)
<!--[if !supportLists]-->71. <!--[endif]--> bsObj=BeautifulSoup(html.read(),"html.parser")
<!--[if !supportLists]-->72. <!--[endif]--> #获取文章的文字内容
<!--[if !supportLists]-->73. <!--[endif]--> for textlist in bsObj.findAll("span",style=re.compile("font-size:([0-9]+)px")):#正则表达式匹配文字内容标签
<!--[if !supportLists]-->74. <!--[endif]--> print(textlist.get_text())
<!--[if !supportLists]-->75. <!--[endif]--> #data_out(textlist.get_text())
<!--[if !supportLists]-->76. <!--[endif]-->
<!--[if !supportLists]-->77. <!--[endif]-->#得到CSDN博客某个博客主页上所有分页的链接,根据分页链接得到每一篇文章的链接并爬取博客每篇文章的文字
<!--[if !supportLists]-->78. <!--[endif]-->pages=set()
<!--[if !supportLists]-->79. <!--[endif]-->def getPageLinks(bokezhuye):
<!--[if !supportLists]-->80. <!--[endif]--> #设置代理IP
<!--[if !supportLists]-->81. <!--[endif]--> #代理IP可以上http://zhimaruanjian.com/获取
<!--[if !supportLists]-->82. <!--[endif]--> proxy_handler=urllib.request.ProxyHandler({'post':'121.22.252.85:8000'})
<!--[if !supportLists]-->83. <!--[endif]--> proxy_auth_handler=urllib.request.ProxyBasicAuthHandler()
<!--[if !supportLists]-->84. <!--[endif]--> opener = urllib.request.build_opener(urllib.request.HTTPHandler, proxy_handler)
<!--[if !supportLists]-->85. <!--[endif]--> urllib.request.install_opener(opener)
<!--[if !supportLists]-->86. <!--[endif]--> #获取网页信息
<!--[if !supportLists]-->87. <!--[endif]--> req=request.Request(bokezhuye,headers=headers1 or headers2 or headers3)
<!--[if !supportLists]-->88. <!--[endif]--> html=urlopen(req)
<!--[if !supportLists]-->89. <!--[endif]--> bsObj=BeautifulSoup(html.read(),"html.parser")
<!--[if !supportLists]-->90. <!--[endif]--> #获取当前页面(第一页)的所有文章的链接
<!--[if !supportLists]-->91. <!--[endif]--> getArticleLinks(bokezhuye)
<!--[if !supportLists]-->92. <!--[endif]--> #去除重复的链接
<!--[if !supportLists]-->93. <!--[endif]--> global pages
<!--[if !supportLists]-->94. <!--[endif]--> for pagelist in bsObj.findAll("a",href=re.compile("^/([A-Za-z0-9]+)(/article)(/list)(/[0-9]+)*$")):#正则表达式匹配分页的链接
<!--[if !supportLists]-->95. <!--[endif]--> if 'href' in pagelist.attrs:
<!--[if !supportLists]-->96. <!--[endif]--> if pagelist.attrs["href"] not in pages:
<!--[if !supportLists]-->97. <!--[endif]--> #遇到了新的界面
<!--[if !supportLists]-->98. <!--[endif]--> newPage=pagelist.attrs["href"]
<!--[if !supportLists]-->99. <!--[endif]--> #print(newPage)
<!--[if !supportLists]-->100. <!--[endif]--> pages.add(newPage)
<!--[if !supportLists]-->101. <!--[endif]--> #获取接下来的每一个页面上的每一篇文章的链接
<!--[if !supportLists]-->102. <!--[endif]--> newPageLink="http://blog.csdn.net/"+newPage
<!--[if !supportLists]-->103. <!--[endif]--> getArticleLinks(newPageLink)
<!--[if !supportLists]-->104. <!--[endif]--> #爬取每一篇文章的文字内容
<!--[if !supportLists]-->105. <!--[endif]--> for articlelist in articles:
<!--[if !supportLists]-->106. <!--[endif]--> newarticlelist="http://blog.csdn.net/"+articlelist
<!--[if !supportLists]-->107. <!--[endif]--> print(newarticlelist)
<!--[if !supportLists]-->108. <!--[endif]--> getArticleText(newarticlelist)
<!--[if !supportLists]-->109. <!--[endif]-->#getArticleLinks("http://blog.csdn.net/hw140701")
<!--[if !supportLists]-->110. <!--[endif]-->getPageLinks("http://blog.csdn.net/hw140701")
<!--[if !supportLists]-->111. <!--[endif]-->#getArticleText("http://blog.csdn.net/hw140701/article/details/55104018")
结果
在其中有时候会出现乱码,这是由于有空格的存在,暂时还有找到方法解决。
另外在有的时候会出现服务器没有响应的错误,如下: