当前位置:   article > 正文

[python爬虫] Selenium爬取内容并存储至MySQL数据库_自动提取网页字段到数据库

自动提取网页字段到数据库

        前面我通过一篇文章讲述了如何爬取CSDN的博客摘要等信息。通常,在使用Selenium爬虫爬取数据后,需要存储在TXT文本中,但是这是很难进行数据处理和数据分析的。这篇文章主要讲述通过Selenium爬取我的个人博客信息,然后存储在数据库MySQL中,以便对数据进行分析,比如分析哪个时间段发表的博客多、结合WordCloud分析文章的主题、文章阅读量排名等。
        这是一篇基础性的文章,希望对您有所帮助,如果文章中出现错误或不足之处,还请海涵。下一篇文章会简单讲解数据分析的过程。


一. 爬取的结果

        爬取的地址为:http://blog.csdn.net/Eastmount

        

        爬取并存储至MySQL数据库的结果如下所示:



        运行过程如下图所示:




二. 完整代码分析

        完整代码如下所示:

  1. # coding=utf-8
  2. from selenium import webdriver
  3. from selenium.webdriver.common.keys import Keys
  4. import selenium.webdriver.support.ui as ui
  5. import re
  6. import time
  7. import os
  8. import codecs
  9. import MySQLdb
  10. #打开Firefox浏览器 设定等待加载时间
  11. driver = webdriver.Firefox()
  12. wait = ui.WebDriverWait(driver,10)
  13. #获取每个博主的博客页面低端总页码
  14. def getPage():
  15. print 'getPage'
  16. number = 0
  17. texts = driver.find_element_by_xpath("//div[@id='papelist']").text
  18. print '页码', texts
  19. m = re.findall(r'(\w*[0-9]+)\w*',texts) #正则表达式寻找数字
  20. print '页数:' + str(m[1])
  21. return int(m[1])
  22. #主函数
  23. def main():
  24. #获取txt文件总行数
  25. count = len(open("Blog_URL.txt",'rU').readlines())
  26. print count
  27. n = 0
  28. urlfile = open("Blog_URL.txt",'r')
  29. #循环获取每个博主的文章摘信息
  30. while n < count: #这里爬取2个人博客信息,正常情况count个博主信息
  31. url = urlfile.readline()
  32. url = url.strip("\n")
  33. print url
  34. driver.get(url)
  35. #获取总页码
  36. allPage = getPage()
  37. print u'页码总数为:', allPage
  38. time.sleep(2)
  39. #数据库操作结合
  40. try:
  41. conn=MySQLdb.connect(host='localhost',user='root',
  42. passwd='123456',port=3306, db='test01')
  43. cur=conn.cursor() #数据库游标
  44. #报错:UnicodeEncodeError: 'latin-1' codec can't encode character
  45. conn.set_character_set('utf8')
  46. cur.execute('SET NAMES utf8;')
  47. cur.execute('SET CHARACTER SET utf8;')
  48. cur.execute('SET character_set_connection=utf8;')
  49. #具体内容处理
  50. m = 1 #第1页
  51. while m <= allPage:
  52. ur = url + "/article/list/" + str(m)
  53. print ur
  54. driver.get(ur)
  55. #标题
  56. article_title = driver.find_elements_by_xpath("//div[@class='article_title']")
  57. for title in article_title:
  58. #print url
  59. con = title.text
  60. con = con.strip("\n")
  61. #print con + '\n'
  62. #摘要
  63. article_description = driver.find_elements_by_xpath("//div[@class='article_description']")
  64. for description in article_description:
  65. con = description.text
  66. con = con.strip("\n")
  67. #print con + '\n'
  68. #信息
  69. article_manage = driver.find_elements_by_xpath("//div[@class='article_manage']")
  70. for manage in article_manage:
  71. con = manage.text
  72. con = con.strip("\n")
  73. #print con + '\n'
  74. num = 0
  75. print u'长度', len(article_title)
  76. while num < len(article_title):
  77. #插入数据 8个值
  78. sql = '''insert into csdn_blog
  79. (URL,Author,Artitle,Description,Manage,FBTime,YDNum,PLNum)
  80. values(%s, %s, %s, %s, %s, %s, %s, %s)'''
  81. Artitle = article_title[num].text
  82. Description = article_description[num].text
  83. Manage = article_manage[num].text
  84. print Artitle
  85. print Description
  86. print Manage
  87. #获取作者
  88. Author = url.split('/')[-1]
  89. #获取阅读数和评论数
  90. mode = re.compile(r'\d+\.?\d*')
  91. YDNum = mode.findall(Manage)[-2]
  92. PLNum = mode.findall(Manage)[-1]
  93. print YDNum
  94. print PLNum
  95. #获取发布时间
  96. end = Manage.find(u' 阅读')
  97. FBTime = Manage[:end]
  98. cur.execute(sql, (url, Author, Artitle, Description, Manage,FBTime,YDNum,PLNum))
  99. num = num + 1
  100. else:
  101. print u'数据库插入成功'
  102. m = m + 1
  103. #异常处理
  104. except MySQLdb.Error,e:
  105. print "Mysql Error %d: %s" % (e.args[0], e.args[1])
  106. finally:
  107. cur.close()
  108. conn.commit()
  109. conn.close()
  110. n = n + 1
  111. else:
  112. urlfile.close()
  113. print 'Load Over'
  114. main()

        在Blog_Url.txt文件中放置需要爬取用户的博客地址URL,如下图所示。注意在此处,作者预先写了个爬取CSDN所有专家的URL代码,这里为访问其他人用于提升阅读量已省略。


        分析过程如下所示。
        1.获取博主总页码
        首先从Blog_Url.txt读取博主地址,然后访问并获取页码总数。代码如下:
  1. #获取每个博主的博客页面低端总页码
  2. def getPage():
  3. print 'getPage'
  4. number = 0
  5. texts = driver.find_element_by_xpath("//div[@id='papelist']").text
  6. print '页码', texts
  7. m = re.findall(r'(\w*[0-9]+)\w*',texts) #正则表达式寻找数字
  8. print '页数:' + str(m[1])
  9. return int(m[1])
        比如获取总页码位17页,如下图所示:



        2.翻页DOM树分析
        这里的 博客翻页采用的是URL连接,比较方便。
        如:
http://blog.csdn.net/Eastmount/article/list/2
        故只需要 :1.获取总页码;2.爬取每页信息;3.URL设置进行循环翻页;4.再爬取。
        也可以采用点击"下页"跳转,没有"下页"停止跳转,爬虫结束,接着爬取下一个博主。


        3.获取详细信息:标题、摘要、时间
        然后审查元素分析每个博客页面,如果采用BeautifulSoup爬取会报错"Forbidden"。
        发现每篇文章都是由一个<div></div>组成,如下所示,只需要定位到该位置即可。



        这里定位到该位置即可爬取,这里需要分别定位标题、摘要、时间。


        代码如下所示。注意,在while中同时获取三个值,它们是对应的。

  1. #标题
  2. article_title = driver.find_elements_by_xpath("//div[@class='article_title']")
  3. for title in article_title:
  4. con = title.text
  5. con = con.strip("\n")
  6. print con + '\n'
  7. #摘要
  8. article_description = driver.find_elements_by_xpath("//div[@class='article_description']")
  9. for description in article_description:
  10. con = description.text
  11. con = con.strip("\n")
  12. print con + '\n'
  13. #信息
  14. article_manage = driver.find_elements_by_xpath("//div[@class='article_manage']")
  15. for manage in article_manage:
  16. con = manage.text
  17. con = con.strip("\n")
  18. print con + '\n'
  19. num = 0
  20. print u'长度', len(article_title)
  21. while num < len(article_title):
  22. Artitle = article_title[num].text
  23. Description = article_description[num].text
  24. Manage = article_manage[num].text
  25. print Artitle, Description, Manage

        4.特殊字符串处理
        获取URL最后一个/后的博主名称、获取字符串时间、阅读数代码如下:

  1. #获取博主姓名
  2. url = "http://blog.csdn.net/Eastmount"
  3. print url.split('/')[-1]
  4. #输出: Eastmount
  5. #获取数字
  6. name = "2015-09-08 18:06 阅读(909) 评论(0)"
  7. print name
  8. import re
  9. mode = re.compile(r'\d+\.?\d*')
  10. print mode.findall(name)
  11. #输出: ['2015', '09', '08', '18', '06', '909', '0']
  12. print mode.findall(name)[-2]
  13. #输出: 909
  14. #获取时间
  15. end = name.find(r' 阅读')
  16. print name[:end]
  17. #输出: 2015-09-08 18:06
  18. import time, datetime
  19. a = time.strptime(name[:end],'%Y-%m-%d %H:%M')
  20. print a
  21. #输出: time.struct_time(tm_year=2015, tm_mon=9, tm_mday=8, tm_hour=18, tm_min=6,
  22. # tm_sec=0, tm_wday=1, tm_yday=251, tm_isdst=-1)



三. 数据库相关操作

        SQL语句创建表代码如下:

  1. CREATE TABLE `csdn` (
  2. `ID` int(11) NOT NULL AUTO_INCREMENT,
  3. `URL` varchar(100) COLLATE utf8_bin DEFAULT NULL,
  4. `Author` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '作者',
  5. `Artitle` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '标题',
  6. `Description` varchar(400) COLLATE utf8_bin DEFAULT NULL COMMENT '摘要',
  7. `Manage` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '信息',
  8. `FBTime` datetime DEFAULT NULL COMMENT '发布日期',
  9. `YDNum` int(11) DEFAULT NULL COMMENT '阅读数',
  10. `PLNum` int(11) DEFAULT NULL COMMENT '评论数',
  11. `DZNum` int(11) DEFAULT NULL COMMENT '点赞数',
  12. PRIMARY KEY (`ID`)
  13. ) ENGINE=InnoDB AUTO_INCREMENT=9371 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
        显示如下图所示:



        其中,Python调用MySQL推荐下面这篇文字。
        [python] 专题九.Mysql数据库编程基础知识
        核心代码如下所示:

  1. # coding:utf-8
  2. import MySQLdb
  3. try:
  4. conn=MySQLdb.connect(host='localhost',user='root',passwd='123456',port=3306, db='test01')
  5. cur=conn.cursor()
  6. #插入数据
  7. sql = '''insert into student values(%s, %s, %s)'''
  8. cur.execute(sql, ('yxz','111111', '10'))
  9. #查看数据
  10. print u'\n插入数据:'
  11. cur.execute('select * from student')
  12. for data in cur.fetchall():
  13. print '%s %s %s' % data
  14. cur.close()
  15. conn.commit()
  16. conn.close()
  17. except MySQLdb.Error,e:
  18. print "Mysql Error %d: %s" % (e.args[0], e.args[1])



        注意,在下载过程中,有的网站是新版本的,无法获取页码。
        比如:http://blog.csdn.net/michaelzhou224
        这时需要简单设置,跳过这些链接,并保存到文件中,核心代码如下所示:

  1. #获取每个博主的博客页面低端总页码
  2. def getPage():
  3. print 'getPage'
  4. number = 0
  5. #texts = driver.find_element_by_xpath("//div[@id='papelist']").text
  6. texts = driver.find_element_by_xpath("//div[@class='pagelist']").text
  7. print 'testsss'
  8. print u'页码', texts
  9. if texts=="":
  10. print u'页码为0 网站错误'
  11. return 0
  12. m = re.findall(r'(\w*[0-9]+)\w*',texts) #正则表达式寻找数字
  13. print u'页数:' + str(m[1])
  14. return int(m[1])
        主函数修改:
  1. error = codecs.open("Blog_Error.txt", 'a', 'utf-8')
  2. #循环获取每个博主的文章摘信息
  3. while n < count: #这里爬取2个人博客信息,正常情况count个博主信息
  4. url = urlfile.readline()
  5. url = url.strip("\n")
  6. print url
  7. driver.get(url+"/article/list/1")
  8. #print driver.page_source
  9. #获取总页码
  10. allPage = getPage()
  11. print u'页码总数为:', allPage
  12. #返回错误,否则程序总截住
  13. if allPage==0:
  14. error.write(url + "\r\n")
  15. print u'错误URL'
  16. continue; #跳过进入下一个博主
  17. time.sleep(2)
  18. #数据库操作结合
  19. try:
  20. .....



        最后希望文章对你有所帮助,如果文章中存在错误或不足之处,还请海涵~
        提高效率,提升科研,认真教学,娜美人生。
      (By:Eastmount 2017-03-13 下午1点半    http://blog.csdn.net/eastmount/  




声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/642574
推荐阅读
相关标签
  

闽ICP备14008679号