当前位置:   article > 正文

python3 爬虫五大模块之四:网页解析器_soup = beautifulsoup(html, 'html.parser') extracte

soup = beautifulsoup(html, 'html.parser') extracted_tags = soup.find_all(is_

Python的爬虫框架主要可以分为以下五个部分:

爬虫调度器:用于各个模块之间的通信,可以理解为爬虫的入口与核心(main函数),爬虫的执行策略在此模块进行定义;

URL管理器:负责URL的管理,包括带爬取和已爬取的URL、已经提供相应的接口函数(类似增删改查的函数)

网页下载器:负责通过URL将网页进行下载,主要是进行相应的伪装处理模拟浏览器访问、下载网页

网页解析器:负责网页信息的解析,这里是解析方式视具体需求来确定

信息采集器:负责将解析后的信息进行存储、显示等处理


代码示例是爬取CSDN博主下的所有文章为例,文章仅作为笔记使用,理论知识rarely

一、网页解析器简介

      解析器的工作就是按需求对网页进行解析,并将解析信息进行处理。

      解析器可以选择的工具有很多种,在这个博客里使用的时BeautifulSoup + 正则表达式进行信息的提取。BeautifulSoup使用起来比较方便(其他的目前还不会,没接触) ,因为不熟,所以不做技术说明,近将经过尝试的结果呈现。

 

二、网页解析器示例:(爬取CSDN博主下的所有文章

  1. # author : sunzd
  2. # date : 2019/3/22
  3. # position: chengdu
  4. from bs4 import BeautifulSoup
  5. from urllib import error
  6. import re
  7. class HtmlParser(object):
  8. def __init__(self):
  9. # self.articles = {}
  10. # self.articles_url = set()
  11. # self.articles_title = set()
  12. # self.articles_date = set()
  13. self.url_page = None
  14. '''
  15. print(link.parent.span) :
  16. <span class="article-type type-1">原</span>
  17. print(link.parent.span.text) :
  18. 节点span的内容:原
  19. print(link.parent.get('href')) :
  20. https://blog.csdn.net/s2603898260/article/details/85067018
  21. https://blog.csdn.net/s2603898260/article/details/85020006
  22. '''
  23. '''
  24. get_article_urls最后的结果只获取了文章的URL,其中大部分代码为调试记录,没删除
  25. '''
  26. def get_article_urls(self, page_url, soup):
  27. # 1. 根据文章类型来确定文章信息
  28. # links = soup.find_all('span', class_=re.compile(r"article-type type-[0-9]"))
  29. # article_titles = soup.find_all('div', attrs={'class':"article-item-box csdn-tracking-statistics",'data-articleid':"\d+"})
  30. # article_info = soup.find_all('div', class_="info-box d-flex align-content-center")
  31. '''
  32. <div>
  33. --< h4 >
  34. --< p >
  35. --< div >
  36. links = soup.find_all('div', attrs={'class':"article-item-box csdn-tracking-statistics"})
  37. # 获取文章标题信息
  38. print(links[0].h4) # ok
  39. # 获取文章简介信息
  40. print(links[0].div.p)
  41. # 获取文章发表时间、阅读量信息
  42. for child in links[0].div.children:
  43. if len(child) != 3: # 去除空的子标签
  44. continue
  45. print(child.span.text) # print(child.span)
  46. if len(links) > 0:
  47. for link in links:
  48. print(link.next_sibling.next_sibling.next_sibling.next_sibling)
  49. print(link)
  50. print("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-")
  51. '''
  52. articles_url = set()
  53. links = soup.find_all('div', attrs={'class':"article-item-box csdn-tracking-statistics"})
  54. if len(links) > 0:
  55. for link in links:
  56. try:
  57. if link.attrs['style']: # 去除第一个不属于该博主的链接
  58. continue
  59. except KeyError as e:
  60. articles_url.add(link.h4.a.get('href')) # ******文章链接******
  61. # print(link.h4.a.attrs['href']) #get attrs在此等价
  62. # tmp = link.h4.a.text
  63. # tmp = tmp.replace("原", "")
  64. # tmp = tmp.replace("转", "")
  65. # tmp = tmp.replace("\n", "")
  66. # self.articles_title.add(tmp.replace(" ", "")) # 文章标题
  67. # for child in link.div.children:
  68. # if len(child) != 3: # 去除空的子标签
  69. # continue
  70. # # print(child.span.text) # print(child.span)
  71. # self.article_date.add()
  72. # self.articles = dict(zip(self.articles_url, self.articles_title)) 将两个列表合并为字典
  73. # tmp = self.articles_url.pop()
  74. # print(self.articles_url)
  75. # print("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-")
  76. return articles_url
  77. '''
  78. 第一页:
  79. <li data-page="1" class="ui-pager focus">1</li>
  80. <li class="js-page-next js-page-action ui-pager">下一页</li>
  81. <li class="js-page-last js-page-action ui-pager"></li>
  82. 第二页:
  83. <li data-page="2" class="ui-pager focus">2</li>
  84. <li class="js-page-next js-page-action ui-pager ui-pager-disabled">下一页</li>
  85. <li class="js-page-last js-page-action ui-pager ui-pager-disabled"></li>
  86. '''
  87. def get_page_url(self, page_url, soup):
  88. if page_url is None or soup is None:
  89. return None
  90. # https://blog.csdn.net/s2603898260/article/list/1?
  91. # 获取当前页
  92. cur_page = soup.find('li', attrs={'class':"ui-pager focus"}) #attrs={'class':"ui-pager focus"}
  93. print(cur_page)
  94. # 判断是否有下一页
  95. # links = soup.find('li', class_=re.compile(r"js-page-last.+ui-pager-disabled"))
  96. links = soup.find('li', class_="js-page-next js-page-action ui-pager ui-pager-disabled")
  97. if links is None or len(links) == 0:
  98. self.url_page = None
  99. return self.url_page
  100. # 寻找下一页
  101. # TODO:
  102. return self.url_page
  103. def parser(self, page_url, html):
  104. if html is None or page_url is None:
  105. print("html or page_url is None")
  106. return None
  107. soup = BeautifulSoup(html, 'html.parser', from_encoding='utf-8')
  108. articles = self.get_article_urls(page_url, soup)
  109. #new_page = self.get_page_url(page_url, soup)
  110. return articles

 

三、上述代码用到的知识点:

       1. BeautifulSoup Note:

soup = BeautifulSoup(html, 'html.parser', from_encoding='utf-8')      # 将html转换为标记树的形式soup

 使用find_all()寻找符合属性的所有节点信息:

article_titles = soup.find_all('div', attrs={'class':"article-item-box csdn-tracking-statistics",'data-articleid':"\d+"})

 可以使用find()寻找符合属性的第一个节点信息,一般这个节点为大节点.(以下为假设)

  1.  如博客的正文节点<div>,可以先通过find找到<div>, 然后在一次遍历其他的节点、寻找所有符合要求的图片等 
  2. # find('div',attrs={}).find_all('p',attrs={})
  3. # <div>
  4.  # ----< h4 >
  5.  # ----< p >
  6.  # ----< div >  
  7. # ---------< p >
  8. # ---------< p >
  9. # ---------< p >
  10. # 获取文章标题信息
  11. print(links[0].h4) # ok
  12. # 获取文章简介信息
  13. print(links[0].div.p)
  14. # 获取文章发表时间、阅读量信息
  15. for child in links[0].div.children:
  16. if len(child) != 3: # 去除空的子标签
  17. continue
  18. # print(child.span.text) #打印节点文本信息
  19. # print(child.span) #打印整个节点信息

打印节点属性信息:

# print(link.h4.a.get('href'))    # 文章链接
# print(link.h4.a.attrs['href'])  # 文章链接 两个等价

 

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

闽ICP备14008679号