继续上次的笔记, 继续完善csdn博文的提取.

发现了非常好的模块. html2docx

结果展示:

运行之后, 直接生成docx文档. 截个图如下:

结果已经基本满意了!!!

在编写过程中的一些感想.

  1. 获取网站响应:

    决定放弃requests, 采用 selenium.webdriver.

    后者就是模拟浏览器操作. 可以应对许多需要登录的, 防止爬取的网站

    超时控制(等待网站响应), 操作网页等功能也非常强大.

  2. 定位页面元素:

    在定位页面元素方面: 有太多的方法可以选择. 最后决定就用一种. webdriver方法.

    放弃etree, BeautifulSoup, 还有直接用re模块的提取.

  3. 好好学习并掌握webdriver一种办法, 就可以了. 它的功能已经非常强大了,

    也支持用xpath来锁定页面元素.

  4. webdriver支持 网页面里注入javascript脚本来完成任务. (网络开发里的前端技术)

  5. 为了与html2docx衔接, 这里利用了

    selenium.webdriver.WebElemnt.get_attribute('outHTML')方法获取元素的html

    BeautifulSoup对象的prettify()方法, 来生成合法的完整的页面元素的html源码.

代码:

  1. import os; type(os)
  2. import time; type(time)
  3. import re
  4. anys = '.*?' # 任意长的字符串, 贪婪型的
  5. import random; type(random)
  6. #import requests
  7. #from lxml import etree
  8. from selenium import webdriver
  9. chrome_options = webdriver.ChromeOptions()
  10. chrome_options.binary_location = r'C:\Users\Administrator\AppData\Roaming\360se6\Application\360se.exe'
  11. chrome_options.add_argument(r'--lang=zh-CN') # 这里添加一些启动的参数
  12. import logging
  13. logging.basicConfig(level=logging.INFO,
  14. format= '%(asctime)s - %(name)s - %(levelname)s : %(message)s',
  15. #format='%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s %(message)s',
  16. )
  17. logger = logging.getLogger(__name__)
  18. #logger.info("Start print log")
  19. #logger.debug("Do something")
  20. #logger.warning("Something maybe fail.")
  21. #logger.info("Finish")
  22. from bs4 import BeautifulSoup
  23. from html2docx import html2docx
  24. from selenium.webdriver.support.ui import WebDriverWait
  25. from selenium.webdriver.common.by import By
  26. from selenium.webdriver.support import expected_conditions as EC
  27. type(By)
  28. type(EC)
  29. def itm(): return int(time.time())
  30. def insert_title(title:'html w/o Body tag',
  31. article:'html with Body tag'):
  32. '''在article这个完整的合法的html网页里, 在它的头部插入标题部分(title).
  33. 标题部分: 包括文章标题行+作者行+发布日期
  34. '''
  35. merged = re.sub('(<html>\n\s*<body>)',
  36. '<html>\n <body>\n' + title,
  37. article,
  38. flags=re.S,)
  39. return merged
  40. def get_it_wait_untill(browser, element_func='title', sleep_time=80, arg=''):
  41. '''
  42. selenium内核的锁定页面元素, 然后取之. 比如:
  43. 获取网页标题
  44. 获取整个网页的源文件
  45. 获取指定页面元素:
  46. by_id
  47. by_xpath
  48. Example:
  49. >>> get_it_wait_untill(browser, 'title')
  50. >>> get_it_wait_untill(browser, 'page_source')
  51. >>> get_it_wait_untill(browser, element_func='find_element_by_id',
  52. arg='content_views',
  53. )
  54. >>> get_it_wait_untill(browser, element_func='find_element_by_xpath',
  55. arg='//section[@class="content article-content"]',
  56. )
  57. '''
  58. prop = str(type(getattr(browser, element_func)))
  59. #python的很多内置的函数, 是使用C语言写出来的,要看C语言的源代码
  60. if prop == "<class 'str'>":
  61. element = WebDriverWait(browser, sleep_time).until(
  62. lambda x: getattr(x, element_func)
  63. )
  64. #elif callable(getattr(browser, element_func)):
  65. elif prop == "<class 'method'>":
  66. element = WebDriverWait(browser, sleep_time).until(
  67. lambda x: getattr(x, element_func)(arg)
  68. )
  69. return element
  70. def get_csdn_blog(
  71. url='https://blog.csdn.net/Lili_0820/article/details/70155949'
  72. ,
  73. sleep_time=40
  74. ,
  75. ):
  76. '''
  77. 爬取csdn blog文章
  78. 参数:
  79. url: str,
  80. sleep_time: int, wait time in seconds
  81. Example:
  82. >>> get_csdn_blog()
  83. '''
  84. logger.info(f'当前网页的url: {url}')
  85. browser = webdriver.Chrome(options=chrome_options)
  86. browser.implicitly_wait(200)
  87. #timeout_wait = WebDriverWait(browser, 2*5) # 10sec
  88. browser.get(url)
  89. timeout_wait = WebDriverWait(browser, sleep_time) # 10sec;
  90. type(timeout_wait)
  91. '''
  92. 我们需要确保: 网页信息已经全部加载, 否则可能提取不到有用信息.
  93. Sets a sticky timeout to implicitly wait for an element to be found,
  94. or a command to complete.
  95. This method only needs to be called one time per session.
  96. 当浏览器(webdriver实例)在定位元素的时候,
  97. 我们可以设置一个隐式的超时等待时间,
  98. 如果超过这个设定的时间还不能锁定元素, 那么就报错或者继续执行.
  99. 本方法在整个对话期内, 只需调用一次.
  100. '''
  101. title = WebDriverWait(browser, sleep_time).until(lambda x: x.title)
  102. logger.info(f'提取网页标题: {title}')
  103. html= WebDriverWait(browser, sleep_time).until(lambda x: x.page_source)
  104. #html = browser.page_source
  105. #需要花点时间
  106. #time.sleep(sleep_time) # 太粗暴简单了
  107. title = browser.find_element_by_xpath('//h1[@class="title-article"]').text
  108. pub_date = browser.find_element_by_xpath('//div[@class="article-bar-top"]').text
  109. author_url = browser.find_element_by_xpath('//div[@class="article-bar-top"] /a[1]').get_attribute('href')
  110. pub_date = re.findall('\n(.*?)阅读数.*?收藏', pub_date,re.S)[0]
  111. author, pub_date = re.findall('(.*?) (发布.*?) ', pub_date, re.S)[0]
  112. insertion = f'''
  113. <h1> {title} </h1>
  114. <p> {author} ({author_url}) </p>
  115. <p> {pub_date} </p>
  116. '''
  117. content_we = browser.find_element_by_id('content_views') # selenium.webelement
  118. text = content_we.text; type(text)
  119. logger.info('网页源码的长度和博文的长度分别是: {1} {0}'.
  120. format(len(text), len(html))
  121. )
  122. content_html = content_we.get_attribute('outerHTML')
  123. content_html = BeautifulSoup(content_html, 'lxml').prettify()
  124. content_html = insert_title(insertion, content_html)
  125. # 规范化: 输出文件名
  126. # if '|' in title: title2=title.replace('|', '')
  127. # title2 = title2.replace('QuantStart','')
  128. # title2 = title2.replace(' ','_')
  129. outf=f'{title}_{itm()}.docx'
  130. buffer = html2docx(content_html, title=title)
  131. with open(outf, "wb") as fh: fh.write(buffer.getvalue())
  132. if os.path.exists(outf): print( f'{outf} created!!!')
  133. # re方法
  134. '''
  135. pattern = 'id="content_views" class="markdown_views.*?>' + \
  136. '(.*?)' + \
  137. '<link href="https://csdnimg.cn/release/' + \
  138. 'phoenix/mdeditor/markdown_views'
  139. a = re.findall(pattern, html, re.S)
  140. a = a[0]
  141. a = re.findall(f'{anys}(<p>{anys})</div>{anys}', a, re.S)[0]
  142. '''
  143. # etree方法
  144. '''
  145. tree = etree.HTML(html)
  146. cv_etree = tree.xpath('//div[@id="content_views"]')[0]
  147. text = cv_etree.xpath('*/text()')
  148. cv_html = etree.tostring(cv_etree, encoding='unicode')
  149. '''
  150. browser.close()
  151. browser.quit()
  152. #return a
  153. if __name__=='__main__':
  154. pass
  155. # url='https://blog.csdn.net/Lili_0820/article/details/70155949'
  156. # get_csdn_blog(url, sleep_time=80)

spider csdn blog part II的更多相关文章

  1. spider csdn博客和quantstart文章

    spider csdn博客和quantstart文章 功能 提取csdn博客文章 提取quantstart.com 博客文章, Micheal Hall-Moore 创办的网站 特色功能就是: 想把原 ...

  2. 仿CSDN Blog返回页面顶部功能

    只修改了2个地方: 1,返回的速度-->改成了慢慢回去.(原来是一闪而返回) 2,返回顶部图标出现的时机-->改成了只要不在顶部就显示出来.(原来是向下滚动500px后才显示) 注意:JS ...

  3. 用word发CSDN blog,免去插图片的烦恼

    目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...

  4. 用Word 写csdn blog

    目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...

  5. 用word发CSDN blog

    目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...

  6. 使用Genymotion调试出现错误INSTALL_FAILED_CPU_ABI_INCOMPATIBLE解决办法【转自wjr2012的csdn blog】

    点击下载Genymotion-ARM-Translation.zip 将你的虚拟器运行起来,将下载好的zip包用鼠标拖到虚拟机窗口中,出现确认对跨框点OK就行.然后重启你的虚拟机.

  7. 怎么样CSDN Blog投机和增加流量?

    所谓推测装置,以提高它们的可见性,最近比较顾得上,这样一来打字游戏.一方面,练习打字速度 .在又一个方面中,以了解诱导的理论 版权声明:本文博客原创文章,博客,未经同意,不得转载.

  8. 博客导出工具(C++实现,支持sina,csdn,自定义列表)

    操作系统:windowAll 编程工具:visual studio 2013 编程语言:VC++ 最近博文更新的较频繁,为了防止账号异常引起csdn博文丢失,所以花了点时间做了个小工具来导出博文,用做 ...

  9. python爬虫CSDN文章抓取

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/nealgavin/article/details/27230679 CSDN原则上不让非人浏览訪问. ...

随机推荐

  1. global.fun.php

    <?php /**   所有公共函数文件*/ /**    序列化*/function _serialize($obj){    return base64_encode(gzcompress( ...

  2. mac上mamp用navigate连接不上

    参考 http://blog.sina.com.cn/s/blog_6742643c0100r9qp.html

  3. MacBook 启用或停用 root 用户

    启用或停用 root 用户 选取苹果菜单 () >“系统偏好设置”,然后点按“用户与群组”(或“帐户”). 点按 ,然后输入管理员名称和密码. 点按“登录选项”. 点按“加入”(或“编辑”). ...

  4. mysql8.0 安装版没有my.ini

    这时候,打开 benchmark,看一下实际路径就好了

  5. 2019.8.14 NOIP模拟测试21 反思总结

    模拟测试20的还没改完先咕着 各种细节问题=错失190pts T1大约三分钟搞出了式子,迅速码完,T2写了一半的时候怕最后被卡评测滚去交了,然后右端点没有初始化为n…但是这样还有80pts,而我后来还 ...

  6. db link的查看创建与删除 1

    1.查看dblink select owner,object_name from dba_objects where object_type='DATABASE LINK'; 或者 select * ...

  7. Codeforces 1150D(字符串dp)

    反思 三维的dp压根没看出来,看题解以后思路又很直观,找几道字符串dp练练才行 序列自动机和优化一维略 /* __ __ * ____| |_____| |____ * | | * | __ | * ...

  8. golang学习资料必备

    核心资料库 https://github.com/yangwenmai/learning-golang

  9. reverse 的用法

    直接对数组或是数据结构使用 #include<bits/stdc++.h> using namespace std; ]={,,,,,};//申请6个元素,下标从0开始,最后一个下标是5 ...

  10. QT_string转char*

    char* convertQString2char(const QString &str) { QByteArray ba = str.toUtf8(); char * pathChar = ...