spider csdn blog part II
继续上次的笔记, 继续完善csdn博文的提取.
发现了非常好的模块. html2docx
结果展示:
运行之后, 直接生成docx文档. 截个图如下:
结果已经基本满意了!!!
在编写过程中的一些感想.
获取网站响应:
决定放弃requests, 采用 selenium.webdriver.
后者就是模拟浏览器操作. 可以应对许多需要登录的, 防止爬取的网站
超时控制(等待网站响应), 操作网页等功能也非常强大.定位页面元素:
在定位页面元素方面: 有太多的方法可以选择. 最后决定就用一种. webdriver方法.
放弃etree, BeautifulSoup, 还有直接用re模块的提取.好好学习并掌握webdriver一种办法, 就可以了. 它的功能已经非常强大了,
也支持用xpath来锁定页面元素.webdriver支持 网页面里注入javascript脚本来完成任务. (网络开发里的前端技术)
为了与html2docx衔接, 这里利用了
selenium.webdriver.WebElemnt.get_attribute('outHTML')方法获取元素的html
BeautifulSoup对象的prettify()方法, 来生成合法的完整的页面元素的html源码.
代码:
import os; type(os)
import time; type(time)
import re
anys = '.*?' # 任意长的字符串, 贪婪型的
import random; type(random)
#import requests
#from lxml import etree
from selenium import webdriver
chrome_options = webdriver.ChromeOptions()
chrome_options.binary_location = r'C:\Users\Administrator\AppData\Roaming\360se6\Application\360se.exe'
chrome_options.add_argument(r'--lang=zh-CN') # 这里添加一些启动的参数
import logging
logging.basicConfig(level=logging.INFO,
format= '%(asctime)s - %(name)s - %(levelname)s : %(message)s',
#format='%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s %(message)s',
)
logger = logging.getLogger(__name__)
#logger.info("Start print log")
#logger.debug("Do something")
#logger.warning("Something maybe fail.")
#logger.info("Finish")
from bs4 import BeautifulSoup
from html2docx import html2docx
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
type(By)
type(EC)
def itm(): return int(time.time())
def insert_title(title:'html w/o Body tag',
article:'html with Body tag'):
'''在article这个完整的合法的html网页里, 在它的头部插入标题部分(title).
标题部分: 包括文章标题行+作者行+发布日期
'''
merged = re.sub('(<html>\n\s*<body>)',
'<html>\n <body>\n' + title,
article,
flags=re.S,)
return merged
def get_it_wait_untill(browser, element_func='title', sleep_time=80, arg=''):
'''
selenium内核的锁定页面元素, 然后取之. 比如:
获取网页标题
获取整个网页的源文件
获取指定页面元素:
by_id
by_xpath
Example:
>>> get_it_wait_untill(browser, 'title')
>>> get_it_wait_untill(browser, 'page_source')
>>> get_it_wait_untill(browser, element_func='find_element_by_id',
arg='content_views',
)
>>> get_it_wait_untill(browser, element_func='find_element_by_xpath',
arg='//section[@class="content article-content"]',
)
'''
prop = str(type(getattr(browser, element_func)))
#python的很多内置的函数, 是使用C语言写出来的,要看C语言的源代码
if prop == "<class 'str'>":
element = WebDriverWait(browser, sleep_time).until(
lambda x: getattr(x, element_func)
)
#elif callable(getattr(browser, element_func)):
elif prop == "<class 'method'>":
element = WebDriverWait(browser, sleep_time).until(
lambda x: getattr(x, element_func)(arg)
)
return element
def get_csdn_blog(
url='https://blog.csdn.net/Lili_0820/article/details/70155949'
,
sleep_time=40
,
):
'''
爬取csdn blog文章
参数:
url: str,
sleep_time: int, wait time in seconds
Example:
>>> get_csdn_blog()
'''
logger.info(f'当前网页的url: {url}')
browser = webdriver.Chrome(options=chrome_options)
browser.implicitly_wait(200)
#timeout_wait = WebDriverWait(browser, 2*5) # 10sec
browser.get(url)
timeout_wait = WebDriverWait(browser, sleep_time) # 10sec;
type(timeout_wait)
'''
我们需要确保: 网页信息已经全部加载, 否则可能提取不到有用信息.
Sets a sticky timeout to implicitly wait for an element to be found,
or a command to complete.
This method only needs to be called one time per session.
当浏览器(webdriver实例)在定位元素的时候,
我们可以设置一个隐式的超时等待时间,
如果超过这个设定的时间还不能锁定元素, 那么就报错或者继续执行.
本方法在整个对话期内, 只需调用一次.
'''
title = WebDriverWait(browser, sleep_time).until(lambda x: x.title)
logger.info(f'提取网页标题: {title}')
html= WebDriverWait(browser, sleep_time).until(lambda x: x.page_source)
#html = browser.page_source
#需要花点时间
#time.sleep(sleep_time) # 太粗暴简单了
title = browser.find_element_by_xpath('//h1[@class="title-article"]').text
pub_date = browser.find_element_by_xpath('//div[@class="article-bar-top"]').text
author_url = browser.find_element_by_xpath('//div[@class="article-bar-top"] /a[1]').get_attribute('href')
pub_date = re.findall('\n(.*?)阅读数.*?收藏', pub_date,re.S)[0]
author, pub_date = re.findall('(.*?) (发布.*?) ', pub_date, re.S)[0]
insertion = f'''
<h1> {title} </h1>
<p> {author} ({author_url}) </p>
<p> {pub_date} </p>
'''
content_we = browser.find_element_by_id('content_views') # selenium.webelement
text = content_we.text; type(text)
logger.info('网页源码的长度和博文的长度分别是: {1} {0}'.
format(len(text), len(html))
)
content_html = content_we.get_attribute('outerHTML')
content_html = BeautifulSoup(content_html, 'lxml').prettify()
content_html = insert_title(insertion, content_html)
# 规范化: 输出文件名
# if '|' in title: title2=title.replace('|', '')
# title2 = title2.replace('QuantStart','')
# title2 = title2.replace(' ','_')
outf=f'{title}_{itm()}.docx'
buffer = html2docx(content_html, title=title)
with open(outf, "wb") as fh: fh.write(buffer.getvalue())
if os.path.exists(outf): print( f'{outf} created!!!')
# re方法
'''
pattern = 'id="content_views" class="markdown_views.*?>' + \
'(.*?)' + \
'<link href="https://csdnimg.cn/release/' + \
'phoenix/mdeditor/markdown_views'
a = re.findall(pattern, html, re.S)
a = a[0]
a = re.findall(f'{anys}(<p>{anys})</div>{anys}', a, re.S)[0]
'''
# etree方法
'''
tree = etree.HTML(html)
cv_etree = tree.xpath('//div[@id="content_views"]')[0]
text = cv_etree.xpath('*/text()')
cv_html = etree.tostring(cv_etree, encoding='unicode')
'''
browser.close()
browser.quit()
#return a
if __name__=='__main__':
pass
# url='https://blog.csdn.net/Lili_0820/article/details/70155949'
# get_csdn_blog(url, sleep_time=80)
spider csdn blog part II的更多相关文章
- spider csdn博客和quantstart文章
spider csdn博客和quantstart文章 功能 提取csdn博客文章 提取quantstart.com 博客文章, Micheal Hall-Moore 创办的网站 特色功能就是: 想把原 ...
- 仿CSDN Blog返回页面顶部功能
只修改了2个地方: 1,返回的速度-->改成了慢慢回去.(原来是一闪而返回) 2,返回顶部图标出现的时机-->改成了只要不在顶部就显示出来.(原来是向下滚动500px后才显示) 注意:JS ...
- 用word发CSDN blog,免去插图片的烦恼
目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...
- 用Word 写csdn blog
目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...
- 用word发CSDN blog
目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...
- 使用Genymotion调试出现错误INSTALL_FAILED_CPU_ABI_INCOMPATIBLE解决办法【转自wjr2012的csdn blog】
点击下载Genymotion-ARM-Translation.zip 将你的虚拟器运行起来,将下载好的zip包用鼠标拖到虚拟机窗口中,出现确认对跨框点OK就行.然后重启你的虚拟机.
- 怎么样CSDN Blog投机和增加流量?
所谓推测装置,以提高它们的可见性,最近比较顾得上,这样一来打字游戏.一方面,练习打字速度 .在又一个方面中,以了解诱导的理论 版权声明:本文博客原创文章,博客,未经同意,不得转载.
- 博客导出工具(C++实现,支持sina,csdn,自定义列表)
操作系统:windowAll 编程工具:visual studio 2013 编程语言:VC++ 最近博文更新的较频繁,为了防止账号异常引起csdn博文丢失,所以花了点时间做了个小工具来导出博文,用做 ...
- python爬虫CSDN文章抓取
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/nealgavin/article/details/27230679 CSDN原则上不让非人浏览訪问. ...
随机推荐
- Leetcode114. Flatten Binary Tree to Linked List二叉树展开为链表
给定一个二叉树,原地将它展开为链表. 例如,给定二叉树 1 / \ 2 5 / \ \ 3 4 6 将其展开为: 1 \ 2 \ 3 \ 4 \ 5 \ 6 class Solution { publ ...
- mysql本地导入数据
1.获得一个超级权限的用户 grant all on *.* to root@'127.0.0.1' identified by 'root';# 因为我想在本地导入数据,而数据就在本地.# 有时候, ...
- sql 分页rownumber方式
alter procedure [dbo].[proc_getpaging] ( ), --表名(可以为多表) ) = '*', --字段名(全部字段为*) ), --排序字段(支持多字段不用加ord ...
- NOIP2017解题报告
啊不小心点发布了,懒得删了就这样吧,虽然还没写完,也不打算写了大概. d1t1 结论题 没什么好说的 d1t2 模拟 没什么好说的 d1t3 70分算法其实比较好想. 没有0边,就跑最短路,然后按di ...
- Windows Sublime text3 搭建Go语言环境
第一步:Go环境和配置 1.安装 Go 开发环境(省略),假设Go安装目录为 C:\Go 2.配置环境变量,下面两个环境变脸没有就加上. 资料参考:http://studygolang.com/art ...
- 20190922-雅礼Day2
先送大家几个变量名: 具体的可以去$C++ \ Reference$里看(本页 右侧/下侧 有链接) 或者等一下奇迹银桥第三氮 const int c; mutable int a; volatile ...
- Hackerrank--String Function Calculation(后缀数组)
题目链接 Jane loves string more than anything. She made a function related to the string some days ago a ...
- python基础--文件相关操作
文件操作方式的补充: “+”表示的是可以同时读写某个文件 r+:可读可写 w+:可读可写 a+:可读可写 x:只写模式[不可读:不存在则创建,存在则报错] x+:可读可写 文件内的光标移动: 1.re ...
- day38 03-Spring的IOC和DI的区别
在IOC中有一个DI的概念. IOC是控制反转,DI是依赖注入.现在编写的类里面是没有其他的属性的.如果你学过像UML设计的话, 电视没有遥控器,按按钮也可以,但是紧密的那种,像人和四肢,人如果没有了 ...
- HR招聘_(三)_招聘方法论(招聘途径及流程)
1.招聘途径 网络招聘:企业官网,招聘网站,微信,论坛等. 校园招聘:学校信息栏海报,学校组织招聘会,校企业联合专场. 现场招聘会: 专场招聘会,人才市场招聘会. 猎头公司:猎头(年薪高于350K), ...