Python抓取博客记录,获取标题与url
本文最后更新于:2023年4月15日 下午
在博客网站发布了一些博客。总共有四十多篇。现在查看这些博客需要翻页,不是很方便。
想要弄出一个列表,把标题和链接展示出来。如果手动去复制粘贴,耗时耗力,也不够自动化。
有没有什么自动化的方法呢?想到以前用python做过抓取的功能。
开发环境:
- Python3.7
- PyCharm 2018.3.7 (Community Edition)
- macOS 11.4
安装scrapy
我们主要使用的框架是scrapy,官网 https://scrapy.org/
如果需要换用清华的pip源,执行下面的命令1
2pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pip -U
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
根据官网文档进行安装1
pip3 install Scrapy
分析目标网页
目标网页的部分html如下1
2
3
4
5<div class="blog-menu blog-menu-noImg">
<div class="blog-menu-header blog_no_attachment">
<a id="portal_usercenter_2_usernew_blog_title_cus_i_0" href="/blogs/301790" class="common-blog-title" title="Kotlin协程取消与超时" target="_blank" style="margin-left: 0px; color: rgb(51, 51, 51);"><span class="blog-title-wrap" style="overflow-wrap: break-word;">
Kotlin协程取消与超时
</span></a></div>
需要提取的是标题(title)和网址(url)。
shell工具
使用scrapy shell
工具来分析一下目标网页1
scrapy shell 'https://bbs.huaweicloud.com/community/usersnew/id_1606985929124732/page_1'
windows下的url需要用双引号
可以看到如下的运行结果1
2
3
4
5
6
7
8
9
10
11
12
13
14
152021-10-13 09:46:47 [asyncio] DEBUG: Using selector: KqueueSelector
[s] Available Scrapy objects:
[s] scrapy scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s] crawler <scrapy.crawler.Crawler object at 0x7fd889766990>
[s] item {}
[s] request <GET https://bbs.huaweicloud.com/community/usersnew/id_1606985929124732/page_1>
[s] response <200 https://bbs.huaweicloud.com/community/usersnew/id_1606985929124732/page_1>
[s] settings <scrapy.settings.Settings object at 0x7fd88987bb50>
[s] spider <DefaultSpider 'default' at 0x7fd889c7b710>
[s] Useful shortcuts:
[s] fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)
[s] fetch(req) Fetch a scrapy.Request and update local objects
[s] shelp() Shell help (print this help)
[s] view(response) View response in a browser
2021-10-13 09:46:48 [asyncio] DEBUG: Using selector: KqueueSelector
尝试用scrapy的css()
方法来提取元素,操作它的response
变量
例如提取div.blog-menu
1
2
3
4In [2]: response.css('div.blog-menu')
Out[2]:
[<Selector xpath="descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' blog-menu ')]" data='<div class="blog-menu blog-menu-noImg"><'>,
...
可以得到页面上所有满足要求的元素。拿到的元素是Selector,可以再进行下一步的操作。
用for循环读取提取到的元素,在此基础上,去抓取中文标题1
2
3
4
5
6
7
8
9
10
11
12
13In [6]: for item in response.css('div.blog-menu'):
...: print(item.css('a.common-blog-title::attr(title)').extract()[0])
...:
Kotlin协程取消与超时
Android Kotlin协程入门
Kotlin协程基础
Kotlin协程入门
Android View post 方法
Android Activity 传递Parcelable对象
Android Handler,Looper与MessageQueue使用与分析
Android线程池使用介绍
Java线程介绍
使用ECharts绘制网址径向树状图
a.common-blog-title::attr(title)
表示的是我们要查找<a>
里面的内容,指定class为common-blog-title
,并且查找title
属性。css().extract()
将结果列表提取出来。最后得到我们关心的信息。
获取url
同理,把提取部分修改为::attr(href)
代码
前面用shell工具进行分析,我们了解提取目标信息的方法。接下来写Python代码。
在合适的地方新建一个scrapy工程1
scrapy startproject blog
可以得到一系列文件1
2
3
4
5
6
7
8
9blog
spiders
.gitignore
__init__.py
__init__.py
items.py
middlewares.py
pipelines.py
settings.py
在spiders
目录里新建一个文件Hw.py
,它就是我们的“蜘蛛”。完整代码如下。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56import json
import scrapy
def cmp(item):
return item['page']
class HwBlog(scrapy.Spider):
"""
在最外层的blog目录进行操作
scrapy crawl hw
"""
name = "hw" # scrapy crawl hw
res_list = []
req_count = 0
total_url = 5
def start_requests(self):
self.res_list = []
urls = []
base_url = 'https://bbs.huaweicloud.com/community/usersnew/id_1606985929124732/page_'
for i in range(1, self.total_url + 1):
urls.append(base_url + str(i))
for url in urls:
yield scrapy.Request(url=url, callback=self.parse)
def parse(self, response):
self.req_count = self.req_count + 1
page = response.url.split("_")[-1]
for item in response.css('div.blog-menu'):
title_se = item.css("a.common-blog-title")
blog_url = 'https://bbs.huaweicloud.com' + (title_se.css("::attr(href)").extract()[0])
blog_title = title_se.css("::attr(title)").extract()[0]
self.res_list.append({"title": blog_title, "url": blog_url, "page": page})
json_res = json.dumps(self.res_list, ensure_ascii=False)
print(json_res)
res_file_path = 'raw/hw.json'
with open(res_file_path, 'w+') as f:
f.write(json_res)
if self.req_count < self.total_url:
return
res_md = 'raw/hw.md'
self.res_list.sort(key=cmp) # 用页码来排序
with open(res_md, 'w+') as f:
f.writelines('## 华为云社区')
f.write('\n博客数量:' + str(len(self.res_list)) + '\n')
for d in self.res_list:
f.write('\n')
f.write('- [' + d['title'] + '](' + d['url'] + ')')
要启动的话,输入以下命令1
scrapy crawl hw
接下来简单看一下代码
变量
name
是蜘蛛的名字。我们启动的时候会用到它。这个名字由我们自己定义。
res_list
是暂存结果的列表。把获取到的结果暂时存放在里面。
total_url
表示一共要爬几个页面
req_count
表示请求次数
start_requests(self)
在这个方法里进行一些配置工作。比如配置目标url。
我们是预先知道有5个页面,所以配置了5个url。
用scrapy.Request(url=url, callback=self.parse)
构建请求
parse
是回调函数,请求成功后走这个方法。
parse(self, response)
请求成功后,结果保存在response
中。前面用shell进行的操作,可以直接写成python代码。
当请求次数达到目标后,开始写文件。
小结
这是Python scrapy的一次简单应用。
安装scrapy,分析目标网页。把获取到的数据整理后写成markdown文件。
视频在这里