当前位置:   article > 正文

python进行爬虫+数据处理+导入Mysql_python爬虫放进mysql

python爬虫放进mysql

最近有个需求,爬取文章数据供大屏端使用。

菜鸡落泪,记录一下学习过程与踩过的坑

一、爬虫

我选择爬取的网站是云南省应急管理厅的数据url为:云南省应急管理厅 (yn.gov.cn),选取里安全生产的综合监管标题栏下的文章爬取如下:

 

导入所需要的函数库 后从创建列表用于存放数据如下:

  1. '''导入相关库'''
  2. from lxml import etree #解析文档
  3. import bs4
  4. import requests #获取网页
  5. import pandas as pd #保存文件
  6. '''构造循环爬取网页'''
  7. all_content = [] #内容
  8. all_title = [] #爬取的标题存储在列表中
  9. all_time = [] #爬取的时间存储在列表中
  10. url = [] #研究报告网页链接
  11. href = []

然后设置用户代理,获取该目录页面的html超文本标记语言,定位到每篇文章标题

  1. headers = {
  2. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
  3. }#构造头文件,这是模拟真人登录(ps:有缺失,请自己动手)
  4. url1 = f'http://yjglt.yn.gov.cn/html/anquanshengchan/zonghejianguan/'#目标网页链接
  5. res1 = requests.get(url1,headers=headers)#获取网页
  6. soup = bs4.BeautifulSoup(res1.text,"html.parser")#解析
  7. targets1 = soup.find_all("li",class_="list-group-item")#获取目标字段(ps:暂时叫它字段吧),见下面第一张图(图1,依次类推)
  8. #print(len(targets1))
  9. #print(targets1)

 

 接下来就是仔细观察到每篇文章的链接不同,有的以http开头,有的以html开头,用一个if条件判断将其区分开:

 

 

然后就是进入每篇文章的链接,爬取文章的标题、发布时间、文章内容保存于列表,xpath定位相关内容,值得一提的是下面只要时间不要出处,可将xpth中的span改为span[1]。

 

还有就是html开头的链接无效,需要将url补充完整如下:

如此便成功爬取到了数据,将时间列表规范一下,搭建DataFrame对象保存数据为csv文件,代码和文件截图如下:

  1. #爬取的时间列表为双列表,此处用此操作转换为单列表
  2. all_time = [item for sublist in all_time for item in sublist]
  3. #创建DataFrame对象存放数据
  4. data_raw = pd.DataFrame()
  5. data_raw["puth_time"] = all_time
  6. data_raw["title"] = all_title
  7. data_raw["content"] = all_content
  8. #生成CSV文件
  9. data_raw.to_excel("安全生产.xls",index=False,encoding='gbk')#这里我就不放保存路径了,每个人的都不一样
  10. print("安全生产保存成功!")

二、数据处理

爬取得到的数据不是很规范,前面的中括号和换行符特别影响心情,需要把它简单处理,后面的在页面端一般看不到,不做处理,这里我使用python列表切片法,爬取下来的列表切片后为空,查看字符串长度为2,这么多字这么长怎么可能为2?在保存为csv文件后再读取,发现字符串长度变正常了,比title字段,长度大概在90多,直接对字段title和content前面内容切片

  1. #读取文件并将字段类型设置为字符型,如果不保存为CSV文件,许多中文内容字符串长度为2,不方便切片处理,保存之后字符串长度变长,蛮方便处理
  2. data = pd.read_excel('安全生产.xls',dtype = 'str')
  3. #data.head()
  4. #切片处理标题字段和内容字段,将前面的杂乱字符剔除,后面的和中间的多余字符没咋管
  5. title_extra = []
  6. content_extra = []
  7. for i in data["title"]:
  8. #print(i[5:])
  9. title_extra.append(i[7:70])
  10. for i in data["content"]:
  11. #print(i[8:])
  12. content_extra.append(i[8:])

切片后保存为新的csv文件。 

三、插入数据库

因为是小白,之前只接触过一次(抄室友代码),现在自己来入库也是比较曲折,在成功连接自己数据库的基础上,用游标自己写SQL插入多行数据,for循环+execute函数,失败!,直接用executemany函数一次插入多行,也是失败,报错大概意思是字符串占位符不太匹配,要么就是SQL有语法错误。卡了半天没解决,插入部分代码如下:

  1. # 3). *********************插入多条数据****************************
  2. try:
  3. info_1 = all_date_and_resouce
  4. info_2 = all_title
  5. info_3 = all_content
  6. for i in all_title:
  7. print(i)
  8. insert_sqli = "insert into 舆情(title) values(i);"
  9. cur.execute(insert_sqli)
  10. insert_sqli_1 = "insert into 舆情(`time`) values(%s);"
  11. insert_sqli_2 = "insert into 舆情(title) values(%s);"
  12. insert_sqli_3 = "insert into 舆情('content') values(%s);"
  13. cur.executemany(insert_sqli_1, info_1)
  14. cur.executemany(insert_sqli_1, info_1)
  15. cur.executemany(insert_sqli_3, info_3)
  16. except Exception as e:
  17. print("插入多条数据失败:", e)
  18. else:
  19. # 如果是插入数据, 一定要提交数据, 不然数据库中找不到要插入的数据;
  20. conn.commit()
  21. print("插入多条数据成功;")

后来在博客看到一个方法,不用连上数据库手动写SQL,直接将DataFrame数据插入数据库,两行代码完全解决问题!!!

  1. #读取处理后的数据,为导入mqsql做准备
  2. data_final = pd.read_excel('安全生产_final.xls',dtype = 'str')
  3. data_final.head()
  4. #导入相关库
  5. from sqlalchemy import create_engine
  6. #配置mqsql
  7. engine = create_engine("mysql+pymysql://root:123@localhost:3306/db1?charset=utf8mb4")
  8. #导入mysql数据库
  9. data_final.to_sql(name="舆情1",con=engine,if_exists='replace',index=False,index_label=False)
  10. print('插入数据库成功!')

看一下数据库

OK,插入成功!

四、一些思考 

1.爬取数据还得精准定位url,不然数据都找不到。

2.爬虫定位具体数据,re、bs4、xpath三种方式很灵活,用法也很多,处理得当更容易获取规范的数据

3.爬虫还得懂一部分前端知识,

4.python的数据类型,python的双重列表和列表数据提取也挺灵活,有时可以转换为DataFrame用pandas来处理。

5.python中的连接数据库写SQL类似Java的传统JDBC操作,有什么游标啥的,而后面python采用sqlalchemy函数库(第一次见这个东东)一句代码就将DataFrame数据直接插入,感觉比Java的Mybatis框架还NB,只能说我还是个弟弟。

五、存一下源码

  1. '''导入相关库'''
  2. from lxml import etree #解析文档
  3. import bs4
  4. import requests #获取网页
  5. import pandas as pd #保存文件
  6. '''构造循环爬取网页'''
  7. all_content = [] #内容
  8. all_title = [] #爬取的标题存储在列表中
  9. all_time = [] #爬取的时间存储在列表中
  10. url = [] #研究报告网页链接
  11. href = []
  12. headers = {
  13. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
  14. }#构造头文件,这是模拟真人登录(ps:有缺失,请自己动手)
  15. url1 = f'http://yjglt.yn.gov.cn/html/anquanshengchan/zonghejianguan/'#目标网页链接
  16. res1 = requests.get(url1,headers=headers)#获取网页
  17. soup = bs4.BeautifulSoup(res1.text,"html.parser")#解析
  18. targets1 = soup.find_all("li",class_="list-group-item")#获取目标字段(ps:暂时叫它字段吧),见下面第一张图(图1,依次类推)
  19. #print(len(targets1))
  20. #print(targets1)
  21. #判断文章的URL是以html开头还是http开头,如果是以html开头则需要下文进行处理变为标准的URL,才能准确定位到文章
  22. targets_html =[]
  23. targets_http = []
  24. for x in targets1:
  25. y = x.a["href"].startswith("/html")
  26. if y == True:
  27. targets_html.append(x)
  28. else:
  29. targets_http.append(x)
  30. print("html为前缀的文章为:***********************************************************")
  31. print(targets_html)
  32. print("http为前缀的文章为:***********************************************************")
  33. print(targets_http)
  34. #解析文章的内容,通过xpath方法定位到文章的标题、发布时间、文章内容,从而进行爬取
  35. for e in targets_http:
  36. h2=e.a["href"]#获取href里的内容
  37. res3 = requests.get(h2,headers=headers)#解析href的网页链接(即文本链接)
  38. root2 = etree.HTML(res3.text)#再次解析href链接里的内容
  39. '''接下来就是在里面获取内容,后面的步骤与上一篇文章的方法差不多,就不过多赘述啦'''
  40. title1 = root2.xpath("/html/body/div[2]/div[2]/div[2]/div/div[1]/text()")
  41. #print(title)
  42. #提取span[1]就仅仅提取到时间,而没有提取到来源和出处
  43. date_and_resouce1= root2.xpath("//div[contains(@class,'info-container')]//div[contains(@class,'info-title')]//div[contains(@class,'report-subtitle detail-subtitle')]//span[1]//text()")
  44. #source = root.xpath("//div[contains(@class,'content')]//div[@class='creab']//span//a//text()")
  45. #print(company)
  46. content3 = root2.xpath("//div[contains(@class,'info-container')]//div[contains(@class,'info-content')]//p//text()")
  47. #文章内容存在着分割,图片或者表格分割,他在HTML语言中分段存放,所以要将文章内容合并
  48. content4 = "".join(content3)
  49. #print(content2)
  50. #在定义好的总列表添加爬取到的的相关内容
  51. all_title.append(title1)
  52. all_time.append(date_and_resouce1)
  53. all_content.append(content3)
  54. print("第一部分数据爬取完成!")
  55. #html语言开头的URL不规范,此处在其前面添加'http://yjglt.yn.gov.cn/'方能精准定位,其余操作与http开头的url一样
  56. for each in targets_html:
  57. hl=each.a["href"]#获取href里的内容
  58. res2 = requests.get('http://yjglt.yn.gov.cn/'+hl,headers=headers)#解析href的网页链接(即文本链接)见图2
  59. root = etree.HTML(res2.text)#再次解析href链接里的内容
  60. '''接下来就是在里面获取内容,后面的步骤与上一篇文章的方法差不多,就不过多赘述啦'''
  61. title = root.xpath("/html/body/div[2]/div[2]/div[2]/div/div[1]/text()")
  62. #/html/body/div[2]/div[2]/div[2]/div/div[1]/text()
  63. #print(title)
  64. date_and_resouce= root.xpath("//div[contains(@class,'info-container')]//div[contains(@class,'info-title')]//div[contains(@class,'report-subtitle detail-subtitle')]//span[1]//text()")
  65. #source = root.xpath("//div[contains(@class,'content')]//div[@class='creab']//span//a//text()")
  66. #print(company)
  67. content1 = root.xpath("//div[contains(@class,'info-container')]//div[contains(@class,'info-content')]//p//text()")
  68. content2 = "".join(content1)
  69. #print(content2)
  70. all_title.append(title)
  71. all_time.append(date_and_resouce)
  72. all_content.append(content2)
  73. #print(all_title)
  74. #print(all_company)
  75. print("第二部分数据爬取完成!")
  76. #爬取的时间列表为双列表,此处用此操作转换为单列表
  77. all_time = [item for sublist in all_time for item in sublist]
  78. #创建DataFrame对象存放数据
  79. data_raw = pd.DataFrame()
  80. data_raw["puth_time"] = all_time
  81. data_raw["title"] = all_title
  82. data_raw["content"] = all_content
  83. #生成CSV文件
  84. data_raw.to_excel("安全生产.xls",index=False,encoding='gbk')#这里我就不放保存路径了,每个人的都不一样
  85. print("安全生产保存成功!")
  86. #读取文件并将字段类型设置为字符型,如果不保存为CSV文件,许多中文内容字符串长度为2,不方便切片处理,保存之后字符串长度变长,蛮方便处理
  87. data = pd.read_excel('安全生产.xls',dtype = 'str')
  88. #data.head()
  89. #切片处理标题字段和内容字段,将前面的杂乱字符剔除,后面的和中间的多余字符没咋管
  90. title_extra = []
  91. content_extra = []
  92. for i in data["title"]:
  93. #print(i[5:])
  94. title_extra.append(i[7:70])
  95. for i in data["content"]:
  96. #print(i[8:])
  97. content_extra.append(i[8:])
  98. #content_extra
  99. #将处理后的数据保存为CSV文件
  100. data_raw["puth_time"] = all_time
  101. data_raw["title"] = title_extra
  102. data_raw["content"] = content_extra
  103. data_raw.to_excel("安全生产_final.xls",index=False,encoding='gbk')#这里我就不放保存路径了,每个人的都不一样
  104. print("安全生产_final保存成功!")
  105. #读取处理后的数据,为导入mqsql做准备
  106. data_final = pd.read_excel('安全生产_final.xls',dtype = 'str')
  107. data_final.head()
  108. #导入相关库
  109. from sqlalchemy import create_engine
  110. #配置mqsql
  111. engine = create_engine("mysql+pymysql://root:123@localhost:3306/db1?charset=utf8mb4")
  112. #导入mysql数据库
  113. data_final.to_sql(name="舆情1",con=engine,if_exists='replace',index=False,index_label=False)
  114. print('插入数据库成功!')

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

闽ICP备14008679号