Python爬虫自学系列(八)-- 项目实战篇(二)爬取我的所有CSDN博客

在这里插入图片描述

前言

这次玩点刺激的,爬取我的所有博客。
当然,这事儿只有我能干,你们要爬可以爬自己的,后面我会把代码和分析结果放出来。

这两周发生了些不太愉快的事情,反正我现在是挺失望的。


网站分析

获取所有公开博客的链接

刚开始呢,我想找网站地图,看看能不能找到属于我的那一块儿。后来发现是我想多了,网站地图是有,但是那么多博主,一人搞一个也不太现实。于是这条路就走不通了。

接下来,我又去了“文章管理”界面,但是我马上就发现了这是一个动态网页。
我看了看底部的页码,十五页,说多页多,说少也少。反正就挺尴尬一个数的。
我想了想,这个页面比主页要简单点,抓个包看看吧。
找到了文章ID的包,发现网址单独拿出来打不开,于是又放弃了。

最后,我又回到了主页。
底部的页码一看,七页,可以,动手吧。
在这里插入图片描述

我本来想着,链接和标题一起拿了,后来转念一想,,文章里面也是有标题的,到时候一起拿就好了。

于是开始写代码。
有一说一啊,取Xpath的时候,谷歌确实好用,用火狐取出来的Xpath一直放空,谷歌取出来的是相对Xpath,一步到位。

import requests
import threadpool
from lxml import etree
import pandas as pd

cookie = '放你自己的'
header = {
    
    
'User-Agent': '放你自己的',
'Connection': 'keep-alive',
'accept': 'application/json, text/javascript, */*; q=0.01',
'Cookie': cookie,
'referer': '放你自己的主页'
}

url_list = ['https://lion-wu.blog.csdn.net/article/list/1', 'https://lion-wu.blog.csdn.net/article/list/2', 'https://lion-wu.blog.csdn.net/article/list/3', 'https://lion-wu.blog.csdn.net/article/list/4', 'https://lion-wu.blog.csdn.net/article/list/5', 'https://lion-wu.blog.csdn.net/article/list/6', 'https://lion-wu.blog.csdn.net/article/list/7']	# 这个链接很有规律的

keep_url_list = []	# 这个用来

def outdata(url):
    try:
        print('succeed'+url)
        res = requests.get(url,headers=header)
        wbdata = res.content.decode('UTF-8')
        tree = etree.HTML(wbdata)
        el_list = tree.xpath('//*[@id="articleMeList-blog"]/div[2]//div/h4/a/@href')
        print(el_list)
        keep_url_list.append(el_list)

    except:
        print('failed'+url)

def Thread_Pool(outdata,datalist = None,Thread_num = 5):
    '''
    线程池操作,创建线程池、规定线程池执行任务、将任务放入线程池中、收工
    :param outdata: 函数指针,线程池执行的任务
    :param datalist: 给前面的函数指针传入的参数列表
    :param Thread_num: 初始化线程数
    :return: 暂无
    '''
    pool = threadpool.ThreadPool(Thread_num)  # 创建Thread_num个线程

    tasks = threadpool.makeRequests(outdata, datalist)  # 规定线程执行的任务
    # outdata是函数名,datalist是一个参数列表,线程池会依次提取datalist中的参数引入到函数中来执行函数,所以参数列表的长度也就是线程池所要执行的任务数量。

    [pool.putRequest(req) for req in tasks]  # 将将要执行的任务放入线程池中

    pool.wait()  # 等待所有子线程执行完之后退出


Thread_Pool(outdata,datalist=url_list,Thread_num = 7)


#outdata('https://lion-wu.blog.csdn.net/article/list/1')

u2 = []
for i in keep_url_list:
    for j in i:
        print(j)
        u2.append(j)

pd.DataFrame(u2).to_csv('My_CSDN.csv')

网页分析

测试文档

本文使用测试文档:测试文档,要自己动手实现的朋友请打开测试文档跟着操作。

三个问题摆在眼前

随便点开了一篇博客的源码,看到里面不同的部件有不同的标签。
那么这里就涉及到了三个问题:

1、我总共用了多少不同的效果?
2、在爬取的时候,如何使不同的标签下的数据在存储的时候保持原有的顺序
3、标签的标记是否需要留下

问题一解决方案:

第一个问题好办,打开编辑界面就可以很清楚的看到所有的效果了:
在这里插入图片描述

回忆一下我用过的所有效果,有:

文章标题、文内标题、(目录)、加黄标、加粗、斜体、无序、有序、待办、【引用】、【代码块】、【图片】、【表格】、【超链接】、【分隔线】

打括号的是不要的,打中括号的是常用的。

那,要怎么看这些效果在源码里的体现呢,去找是不可能去找的了,写一篇博客,把这些功能都包进去测试就好了。


问题二解决方案:

对于问题二啊,我也纠结了一会儿,因为我不知道Xpath在爬取多个不同标签的时候能否保留住他们原有的顺序。
百度了一会儿,说真的,全是屁话。

于是我就做了个demo测试了一下:

import requests
from lxml import etree

# 前面这一串不再放出

def outdata(url):
    try:
        print('succeed'+url)
        res = requests.get(url,headers=header)
        wbdata = res.content.decode('UTF-8')
        tree = etree.HTML(wbdata)
        el_list = tree.xpath('//*[@id="articleMeList-blog"]/div[2]//div/h4/a')
        for el in el_list:
            e = el.xpath('./text() | ./@href')	 
            # 我特地把顺序反过来,就是要排除这种可能,因为真的开始爬的时候是不会事先让你知道顺序规律的,也没有规律可言。
            print(e)
            
    except:
        print('failed'+url)

outdata('https://lion-wu.blog.csdn.net/article/list/1')

结果证明是成功的,再做点字符串切割切掉转义字符和前后空格就行了。


问题三解决方案

本来以为这个问题是最简单的,只是我想不想留的问题。后来发现不是这样的。

思路一:

对于这个问题,如果直接上手去抓标签里面的文本的话,最终是会丢失掉标签的。
这个问题我想了想,我们可以先将文章标题取下,
之后取下文章正文部分的全部源码,用正则表达式对源码中的各标签打上标记,
之后再用Xpath将文本和链接取出来。

结果:转成字符串之后转不回来了、、、

于是,我又产生了一个想法。

思路二:

首先,非硬性需求的特效就不要了。比方说加粗、斜体、黄标、下划线这种的,就不要了。无序,有序,待办归为一类,也不要了。

这样一选择,那么需要注意的特效(单独再提取一份出来作为标记)就只有:引用、代码块、图片、表格、超链接了。

引用,代码块只标记首尾,表格把表头取出之后底下的也只标记首尾,
超链接和图片链接需要拿出来。

剩下的就交给匹配算法的事情了。

就是说,先把文本和链接全部提取出来,再重头提取一些重要信息

这个只是复杂度高一些,实现还是没问题的。

思路三:

在Xpath提取的时候,看看能不能直接对文本进行标记,如果可以的话,那就最好。


我的选择

我选三,实现了。
方法一里面不是有说,将etree对象转化为字符串吗?
那我完全可以先把标签都选下来,我不取文本,我直接转字符串,这样不就连标签带文本全拿下来了吗?最后我们通过正则表达式将HTML代码中很长的标签转换为比较短的标签。

来看一下从测试文档上抓下来的标签们:

def outdata(url):
    try:
        print('succeed'+url)
        res = requests.get(url,headers=header)
        code = res.apparent_encoding  # 获取url对应的编码格式
        res.encoding = code

        wbdata = res.text
        tree = etree.HTML(wbdata)
        el_list = tree.xpath('//*[@id="content_views"]')

        for el in el_list:
            # e = etree.tostring(el, encoding=code).decode(code)
            # 这一步可以获取文章主体的源码部分

			#界面xpath在下面有提供
            es = el.xpath('./h1 |./h2 |./h3 |./h4 |./h5 |./h6 |./p |./p/mark |./p/span/span/span/span[2]//span/span[2]'
                '|./p/strong |./p/em |./ul//li |./ol//li |./ul//li |./blockquote/p |./pre/code |./p/code '
                '|./div/table/thead/tr//th |./div/table/tbody/tr//td |./hr |./p/img |./p/a')

            for e in es:
                print(etree.tostring(e, encoding=code).decode(code))
                print('-----')	# 调试所用,使得结果更清晰

    except:
        print('failed'+url)

结果:

succeedhttps://lion-wu.blog.csdn.net/article/details/113402976
<p/>

-----
<p/> 

-----
<h1><a id="_2"/>一级标题</h1> 

-----
<h2><a id="_3"/>二级标题</h2> 

-----
<h3><a id="_4"/>三级标题</h3> 

-----
<h4><a id="_5"/>四级标题</h4> 

-----
<h5><a id="_6"/>五级标题</h5> 

-----
<h6><a id="_7"/>六级标题</h6> 

-----
<p>这是一篇测试文档,现在不知道干嘛用很正常,我在写一个爬虫的项目,等我爬虫自学系列最后一篇出来就知道啦,到时候如果你们想复现的话,直接来我这里拿就好。</p> 

-----
<p><span class="katex--display"><span class="katex-display"><span class="katex"><span class="katex-mathml">
     
      
       
        
         a
        
        
         =
        
        
         b
        
        
         +
        
        
         c
        
       
       
         a = b + c 
       
      
     </span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.43056em; vertical-align: 0em;"/><span class="mord mathdefault">a</span><span class="mspace" style="margin-right: 0.277778em;"/><span class="mrel">=</span><span class="mspace" style="margin-right: 0.277778em;"/></span><span class="base"><span class="strut" style="height: 0.77777em; vertical-align: -0.08333em;"/><span class="mord mathdefault">b</span><span class="mspace" style="margin-right: 0.222222em;"/><span class="mbin">+</span><span class="mspace" style="margin-right: 0.222222em;"/></span><span class="base"><span class="strut" style="height: 0.43056em; vertical-align: 0em;"/><span class="mord mathdefault">c</span></span></span></span></span></span></p> 

-----
<span class="mord mathdefault">a</span>
-----
<span class="mord mathdefault">b</span>
-----
<span class="mord mathdefault">c</span>
-----
<p><mark>这是突出字体</mark></p> 

-----
<mark>这是突出字体</mark>
-----
<p><strong>这是加粗字体</strong></p> 

-----
<strong>这是加粗字体</strong>
-----
<p><em>这是斜体</em></p> 

-----
<em>这是斜体</em>
-----
<li>这是无序</li>
-----
<li>这还是无序</li>
-----
<hr/> 

-----
<li>这是有序</li>
-----
<li>这还是有序</li>
-----
<hr/> 

-----
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled"/> 这是待办</li>
-----
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled"/> 这依旧是待办</li>
-----
<li>这是有序</li>
-----
<li>这还是有序</li>
-----
<hr/> 

-----
<p>这里是引用<br/> 这里还是引用</p> 

-----
<code class="prism language-python">代码块在这里
</code>
-----
<hr/> 

-----
<p>这里是引用<br/> 这里还是引用<br/> 这里是引用<br/> 这里还是引用<br/> 这里是引用<br/> 这里还是引用<br/> 这里是引用<br/> 这里还是引用</p> 

-----
<code class="prism language-python">代码块在这里
</code>
-----
<p><img src="https://img-blog.csdnimg.cn/20210129182417155.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNzYyMTkx,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"/></p> 

-----
<img src="https://img-blog.csdnimg.cn/20210129182417155.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNzYyMTkx,size_16,color_FFFFFF,t_70" alt="&#x5728;&#x8FD9;&#x91CC;&#x63D2;&#x5165;&#x56FE;&#x7247;&#x63CF;&#x8FF0;"/>
-----
<p><a href="https://blog.csdn.net/qq_43762191?spm=1001.2101.3001.5343">超链接,顺着网线来打我啊!!!</a></p> 

-----
<a href="https://blog.csdn.net/qq_43762191?spm=1001.2101.3001.5343">超链接,顺着网线来打我啊!!!</a>
-----
<hr/> 

-----
<p>别忘了下划线哦<code>这是行代码</code></p>
                
-----
<code>这是行代码</code>
-----

结果分析

分析一下这里的结果,我们才好对下一步进行决策嘛。

1、首先,第一眼就看到了那一大串标签围绕的公式了,我不记得我还有没有带公式的博客,就留着吧,反正也是一个正则的事情。

2、其次一个很明显的就是重复问题了。
之前直接提取文本的时候不会出现,因为‘/’仅仅提取当前子路径下的所有,但是现在转了字符串,那么‘./p’就成了很多个以‘./p’开头的标签的上级标签了。这时候重复的出现就是必然的了。
在取标签的时候,这似乎是不可调和的矛盾,那就只好在取出标签之后进行一次去重了。
所以我还得写一个去重的函数

3、对于上面这个问题,还有一个解决方法,即在取标签的时候,对于所有以‘./p/’开头的标签全部不留,只留下‘./p’,后面取标签的时候将</p>的优先级设为最低

再看一下效果。

succeedhttps://lion-wu.blog.csdn.net/article/details/113402976
<p/>

-----
<p/> 

-----
<h1><a id="_2"/>一级标题</h1> 

-----
<h2><a id="_3"/>二级标题</h2> 

-----
<h3><a id="_4"/>三级标题</h3> 

-----
<h4><a id="_5"/>四级标题</h4> 

-----
<h5><a id="_6"/>五级标题</h5> 

-----
<h6><a id="_7"/>六级标题</h6> 

-----
<p>这是一篇测试文档,现在不知道干嘛用很正常,我在写一个爬虫的项目,等我爬虫自学系列最后一篇出来就知道啦,到时候如果你们想复现的话,直接来我这里拿就好。</p> 

-----
<p><span class="katex--display"><span class="katex-display"><span class="katex"><span class="katex-mathml">
     
      
       
        
         a
        
        
         =
        
        
         b
        
        
         +
        
        
         c
        
       
       
         a = b + c 
       
      
     </span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.43056em; vertical-align: 0em;"/><span class="mord mathdefault">a</span><span class="mspace" style="margin-right: 0.277778em;"/><span class="mrel">=</span><span class="mspace" style="margin-right: 0.277778em;"/></span><span class="base"><span class="strut" style="height: 0.77777em; vertical-align: -0.08333em;"/><span class="mord mathdefault">b</span><span class="mspace" style="margin-right: 0.222222em;"/><span class="mbin">+</span><span class="mspace" style="margin-right: 0.222222em;"/></span><span class="base"><span class="strut" style="height: 0.43056em; vertical-align: 0em;"/><span class="mord mathdefault">c</span></span></span></span></span></span></p> 

-----
<p><mark>这是突出字体</mark></p> 

-----
<p><strong>这是加粗字体</strong></p> 

-----
<p><em>这是斜体</em></p> 

-----
<li>这是无序</li>
-----
<li>这还是无序</li>
-----
<hr/> 

-----
<li>这是有序</li>
-----
<li>这还是有序</li>
-----
<hr/> 

-----
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled"/> 这是待办</li>
-----
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled"/> 这依旧是待办</li>
-----
<li>这是有序</li>
-----
<li>这还是有序</li>
-----
<hr/> 

-----
<p>这里是引用<br/> 这里还是引用</p> 

-----
<code class="prism language-python">代码块在这里
</code>
-----
<hr/> 

-----
<p>这里是引用<br/> 这里还是引用<br/> 这里是引用<br/> 这里还是引用<br/> 这里是引用<br/> 这里还是引用<br/> 这里是引用<br/> 这里还是引用</p> 

-----
<code class="prism language-python">代码块在这里
</code>
-----
<p><img src="https://img-blog.csdnimg.cn/20210129182417155.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNzYyMTkx,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"/></p> 

-----
<p><a href="https://blog.csdn.net/qq_43762191?spm=1001.2101.3001.5343">超链接,顺着网线来打我啊!!!</a></p> 

-----
<hr/> 

-----
<p>别忘了下划线哦<code>这是行代码</code></p>
                
-----

新结果分析

新结果,不论是在重复方面,还是在文字解码方面,都要优于上面的结果,所以我重新做一次分析。

1、首先,如果判断出来是公式的话,切分之后去掉空的部分,取倒数第二个元素即可。
2、如果是引用的话,还是换这个标签:./blockquote来抓取比较好,因为不排除出现单行引用,那就和</p>区分不了了。
这样获得的结果就是:

<blockquote> 
 <p>这里是引用</p> 
</blockquote> 

或者

<blockquote> 
 <p>这里是引用<br/> 这里还是引用<br/> 这里是引用<br/> 这里还是引用<br/> 这里是引用<br/> 这里还是引用<br/> 这里是引用<br/> 这里还是引用</p> 
</blockquote> 

3、在获取图片链接的时候,要注意将前后剔除干净。
4、注意行代码的提取。
5、正则时,既要提取标签,也要提取出文字,需要注意存放的问题。

其他的也没有啥了


界面Xpath

首先,标记以及正文部分都在这个标签之下://*[@id="mainBox"]/main/div[1]
标题在这里://*[@id="articleContentId"]
正文在这里://*[@id="content_views"]


文中标题所在位置:
//*[@id="content_views"]//h1
//*[@id="content_views"]//h2
//*[@id="content_views"]//h3
//*[@id="content_views"]//h4
//*[@id="content_views"]//h5
//*[@id="content_views"]//h6


段落文本所在位置://*[@id="content_views"]//p
黄色标标所在位置://*[@id="content_views"]//p/mark
公式------所在位置://*[@id="content_views"]//p/span/span/span/span[2]//span/span[2]
黑色加粗所在位置://*[@id="content_views"]//p/strong
斜体字—所在位置://*[@id="content_views"]//p/em


无序标签所在位置://*[@id="content_views"]//ul//li/text()
有序标签所在位置://*[@id="content_views"]//ol//li/text()
待办和无序是一样的,不管了,反正也只是用着好玩。
引用标签所在位置://*[@id="content_views"]//blockquote/p//text()


代码块儿所在位置://*[@id="content_views"]//pre/code/text()
行代码—所在位置://*[@id="content_views"]//p/code
超链接—所在位置://*[@id="content_views"]//p/a


表格表头所在位置://*[@id="content_views"]//div/table//th
表格内容所在位置://*[@id="content_views"]//div/table//td
下划线—所在位置://*[@id="content_views"]//hr


图片://*[@id="content_views"]//p/img



爬取一篇博客

经过上面缜密的分析,我准备完整的爬取一篇博客并保存到正确的文件中。
爬哪篇呢?自然是测试文档了。

正则表达式分析

经过一会儿的努力,我写出了这样的正则表达式:

res = re.findall('(<.+?>)',string = string)
#res2 = re.findall('(>.*?<)',string = string)
res2 = re.findall('(>[\s\S]*?<)',string=string)
print(res)

# 因为在提取第二个正则表达式的时候,会带上‘>’和‘<’,所以需要剔除一下
for r2 in range(len(res2)):
	res2[r2] = res2[r2].replace('>', '').replace('<', '').replace('\n', '').strip()
    # 在遍历时修改需要使用下标
    # 字符串一旦写完,就不能通过下标对其进行修改
	
for r3 in res2[:]:  # 不用res2[:]的话,遍历会跳步
    if r3 == '':
        res2.remove(r3)

result = ''.join(res2)	# 这里不应该简单整合,这个整合给公式就好了。
# 这段操作稍后会单独整理一份博客。

print(result)

正则表达式测试

首先,拿最简单的先试一下:

string = '<h1><a id="_2"/>一级标题</h1>'

['<h1>', '<a id="_2"/>', '</h1>']
一级标题

说明这个表达式初步可用了。


再拿长一点的:

['<p>', '</p>']
这是一篇测试文档,现在不知道干嘛用很正常,我在写一个爬虫的项目,等我爬虫自学系列最后一篇出来就知道啦,到时候如果你们想复现的话,直接来我这里拿就好。

应该可以看出来拿的是哪个啊。


接下来,就是我们前面看着就烦的公式部分了。
能否成功呢?

string = '''<p><span class="katex--display"><span class="katex-display"><span class="katex"><span class="katex-mathml">




         a


         =


         b


         +


         c



         a = b + c


     </span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.43056em; vertical-align: 0em;"/><span class="mord mathdefault">a</span><span class="mspace" style="margin-right: 0.277778em;"/><span class="mrel">=</span><span class="mspace" style="margin-right: 0.277778em;"/></span><span class="base"><span class="strut" style="height: 0.77777em; vertical-align: -0.08333em;"/><span class="mord mathdefault">b</span><span class="mspace" style="margin-right: 0.222222em;"/><span class="mbin">+</span><span class="mspace" style="margin-right: 0.222222em;"/></span><span class="base"><span class="strut" style="height: 0.43056em; vertical-align: 0em;"/><span class="mord mathdefault">c</span></span></span></span></span></span></p> '''

结果:

['<p>', '<span class="katex--display">', '<span class="katex-display">', '<span class="katex">', '<span class="katex-mathml">', '</span>', '<span class="katex-html">', '<span class="base">', '<span class="strut" style="height: 0.43056em; vertical-align: 0em;"/>', '<span class="mord mathdefault">', '</span>', '<span class="mspace" style="margin-right: 0.277778em;"/>', '<span class="mrel">', '</span>', '<span class="mspace" style="margin-right: 0.277778em;"/>', '</span>', '<span class="base">', '<span class="strut" style="height: 0.77777em; vertical-align: -0.08333em;"/>', '<span class="mord mathdefault">', '</span>', '<span class="mspace" style="margin-right: 0.222222em;"/>', '<span class="mbin">', '</span>', '<span class="mspace" style="margin-right: 0.222222em;"/>', '</span>', '<span class="base">', '<span class="strut" style="height: 0.43056em; vertical-align: 0em;"/>', '<span class="mord mathdefault">', '</span>', '</span>', '</span>', '</span>', '</span>', '</span>', '</p>']

a=b+c

看得出来,很成功啊!!!

但是,等下的算法里面不能忘记对链接的处理,他们可都在标签里面呢!!!


状态机

前面的代码好像还有一点改动,记不得了。
有了这个状态机,就可以初步的把标签啥的都打上去了。
当然,还有需要改动的地方,只是目前我觉得性价比不高,就没写。

def get_div_name(div_list):
    '''
    这是一个用于提取标签的状态机
    :param div_list: 标签列表
    :return: 最终标签名
    '''
    if div_list[0] == '<hr/>':
        return '【下划线】'
    elif div_list[0][1] == 'h':
        hn = re.search('[0-9]{1}',div_list[0]).group(0)
        return '【' + hn + '级标题】'
    elif div_list[0] == '<li>':
        return '【枚举】'
    elif div_list[0] == '<li class="task-list-item">':
        return '【待办】'
    elif div_list[0] == '<blockquote>':
        return '【引用】'
    elif '<code class' in div_list[0]:
        l = re.search('(-.+?")',div_list[0])
        language = l.group(0).replace('-','').replace('"','')
        return '【'+language+'语言代码块儿】'
    elif div_list[0] == '<p>':
        if div_list[1] == '</p>':
            return '【纯文本】'
        elif 'katex' in div_list[1]:
            return '【公式】'
        elif div_list[1] == '<mark>':
            return '【黄标突出】'
        elif div_list[1] == '<strong>':
            return '【加粗】'
        elif div_list[1] == '<em>':
            return '【斜体】'
        elif div_list[1] == '<code>':
            return '【行代码】'
        elif 'img' in div_list[1]:
            h = re.search('(".+?")',div_list[1])
            href = h.group(0).replace('"','').replace('"','')
            return '【图片】:' + href
        elif 'href' in div_list[1]:
            h = re.search('(".+?")', div_list[1])
            href = h.group(0).replace('"', '').replace('"', '')
            return '【超链接:】'+ href
        else:
        	return ''
    else:
        return ''

def outdata(url):
    try:
        print('succeed'+url)
        res = requests.get(url,headers=header)
        code = res.apparent_encoding  # 获取url对应的编码格式
        res.encoding = code

        wbdata = res.text
        tree = etree.HTML(wbdata)
        el_list = tree.xpath('//*[@id="content_views"]')

        for el in el_list:

            es = el.xpath('./h1 | ./h2 | ./h3 | ./h4 | ./h5 | ./h6 | ./p |./ul//li | ./ol//li | ./ul//li | ./blockquote | ./pre/code '
                '| ./div/table/thead/tr//th | ./div/table/tbody/tr//td | ./hr')

            for e in es:
                string = etree.tostring(e,encoding=code).decode(code)
                res = re.findall('(<.+?>)', string=string)
                res2 = re.findall('(>[\s\S]*?<)', string=string)
                div_name = get_div_name(res)
                for r2 in range(len(res2)):
                    res2[r2] = res2[r2].replace('>', '').replace('<', '').replace('\n', '').strip()

                for r3 in res2[:]:  # 不用res2[:]的话,遍历会跳步
                    if r3 == '':
                        res2.remove(r3)

                if div_name != '':
                    res2.insert(0,div_name)

                print('\n'.join(res2))
                print('-----')

    except:
        print('failed'+url)

保存到文件

接近尾声了啊。
又做了点微调,然后将数据保存到了文件里面。

def save_to_file(file_name,contant):
    '''
    这个函数用于将数据写入到文件中
    :param file_name:文件名
    :param contant: 文件内容
    :return: none
    '''
    file_path = r'D:\CSDN博客'
    if not os.path.exists(file_path):   # 如果目标文件夹不存在
        os.mkdir(file_path)
    w_file_path = file_path+'\\'+'file_name'+'.txt'
    f = open(w_file_path,'w')
    for c in contant:
        f.write(c)
    f.close()

获取全部博客

其实吧,也就是扔进线程池里去处理。
所以就在下面加两行线程池的启动即可:

url_list = pd.read_csv('My_CSDN.csv')['url']

Thread_Pool(outdata,datalist=url_list,Thread_num = 10)

简陋了点,但是1.0版本是出来了,接下来就是优化的事情了。

本文代码还算详尽,要拿完整代码,扫旁边二维码,后台回复:“博客”,获取当前最新版本。
2021.2.1好前会放上第一个版本。

在这里插入图片描述

至于私密博客,回头优化的时候会带上。

在这里插入图片描述

有感情是一回事儿,被欺骗是另一回事儿。被伤过的心还怎么再爱呢?

猜你喜欢

转载自blog.csdn.net/qq_43762191/article/details/113367421