思维之海

——在云端,寻找我的星匙。

网络爬虫基理

爬虫,一种按照一定的规则、自动地抓取万维网信息的程序或者脚本。

  • 初衷:为搜索引擎服务
  • 现状:自动化或批量的数据获取

爬虫务必关注robots.txt,这是网站与爬虫之间的君子协议。

References

学堂在线 - 计算未来云讲坛 - Python网络爬虫,饶淙元

Intro

学堂在线 - 计算未来云讲坛 - Python网络爬虫,饶淙元

浏览网站的基本过程

  • 域名解析:由DNS(Domain Name Server)完成,如果被劫持则会找到错误的结果
  • 请求发送:将信息直接传到目标服务器上,由服务器决定处理与返回的结果
  • 响应处理:浏览器渲染结果并呈现给你,随后用户为所欲为(例:浏览器页面修改【前端修改】)

终极哲学三连发

(服务器器视角下的网络请求)

  • 你是谁:User-Agent | Cookies
    • User-Agent:协议的头部(Header)信息中的一部分
    • Cookie:一组字典串,用于唯一标识访问者
      • 比如:BD_HOME=1;BDSVRTM=154;。(以百度为例)
  • 你从哪里来:IP
  • 你来这里干什么:Method & Parameter

在这个过程中服务器可能面临一些攻击(爬虫可能无意间导致这样的问题)

  • DoS(Denial of Service) attack:拒绝服务攻击,让服务器无法正常服务,可以通过构造大量的请求使服务器“忙不过来”完成
  • DDoS(Distributed Denial of Service) attack:分布式拒绝服务攻击,在DoS攻击基础上改为多个客户端(用户)同时对目标网站发起大量请求

网络抓包

浏览网页的本质使基于HTTP协议的一次或多次网络请求,这些请求用户是可以直接查看的,比如按下F12再看看“网络”。

网络抓包通常有如下用处:

  • 查看真正的数据来源(常为XHR
  • 查看下载视频等数据
  • 模拟请求完成登录
  • 测试网站安全性

比如,如果你想下载直播回放的话,只需要有一款现代浏览器与ffmpeg(需要在linux上搞)就足以应付很多情况。比如你想下载一个装机教程的话……

robots.txt 君子协议

必应

必应的爬虫协议:(https://www.baidu.com/robots.txt)

除了钦点的几个爬虫之外,其它拒不接待。

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
User-agent: Baiduspider
Disallow: /baidu
Disallow: /s?
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Googlebot
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: MSNBot
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Baiduspider-image
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: YoudaoBot
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Sogou web spider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Sogou inst spider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Sogou spider2
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Sogou blog
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Sogou News Spider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Sogou Orion spider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: ChinasoSpider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Sosospider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh


User-agent: yisouspider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: EasouSpider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: *
Disallow: /

天猫

天猫的协议:(https://list.tmall.com/robots.txt)

谁也不能爬,啥也不能爬。

1
2
User-agent: *
Disallow: /

天猫主页(https://tmall.com)没有robots.txt协议,所以是可以爬的。

虎扑

https://www.hupu.com/robots.txt

1
2
3
4
5
6
7
User-agent: *
Allow: /

Sitemap: https://bbs.hupu.com/sitemap_index.xml
Sitemap: https://bbs.hupu.com/sitemap/sitemap_boards.xml
Sitemap: https://voice.hupu.com/sitemap_index.xml
Sitemap: https://nba.hupu.com/players/index.xml

虎扑BBS

https://bbs.hupu.com/robots.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
User-agent: *
Request-rate: 50/1
Disallow: /api/
Disallow: /ajax/
Disallow: /profile.php?*
Disallow: /hack/
Disallow: /template/
Disallow: /attachment/
Disallow: /gearfeedback/
Disallow: /*_*.html$

Sitemap: https://bbs.hupu.com/sitemap_index.xml
Sitemap: https://bbs.hupu.com/sitemap/sitemap_boards.xml

注意到Request-rate: 50/1,一秒钟最多发送50个请求。

多发请求虎扑可能请你喝茶QAQ

法无禁止皆可为

注意:/*_*.html$只限制了.html_的,一般的 bbs 网址这部分是纯数字的,因此是可以爬取的。

爬虫框架

理想框架(企业级)

理想框架(入门版)

从多线程到单线程。

Scheduler(调度器)在这里的作用比如说,每天定时爬取某些信息(新闻、天气……),当没有爬取任务的时候自动调度为休眠状态。

爬虫工具

Python经济套装:

  • Python 3
  • Pycharm:强大的 Python IDE。或替代品
  • requests:一个用于发起请求的 Python 库
  • BeautifulSoup4:一个用于解析 html 的 Python 库

Pycharm 导入 Python 包、模块(先引入需要用到的库)

自学内容

  • Python基础
  • 娴熟的搜索引擎使用技巧(学习广泛、特殊、高级的爬虫技术)
  • 文件编码处理
  • js2py:在 Python 中执行 JavaScript 脚本
  • pypeteer:通过 headless 的方法直接渲染网页
  • scrapy:真正的高性能爬虫框架

注:Script = 脚本。

基本爬虫练习

卫健委爬虫套装:https://github.com/rcy17/wjw_scrawler


爬取北京市卫健委

以北京市卫健委为例:

简单测试

在构建好Python+PyCharm环境以后,使用GET方法获取网站信息,响应正常。

(可选)如果编码不正常,可以预先解码:print(response.content.decode('utf-8'))


然而仔细看获取的text内容会发现:

1
....最近有可疑的攻击行为,请稍后重试.' || '当前访问疑似黑客攻击,已被网站管理员设置为拦截'....

被拦截了。重新通过浏览器打开网站会发现:

看来通过简单的get操作已经无法通过查验。很可能创宇云安全捕获了Python在发送请求时的一些特征码或者特征字段,并加以拦截。这是一种不让爬取的手段。

窗口预模拟

一个简单的技巧是,在正式运行爬取脚本之前,新开一个python命令行窗口,预先边写边运行,便于评估爬取效果。(这是因为python是解释型语言)

html解析

不如爬取我自己的博客试试好了。

注意:BeautifulSoup只能解析response的content:https://www.cnblogs.com/fallenmoon/p/8342241.html,而不能直接解析response。

1
2
3
response = get("https://vel.life/")
data = response.content
soup = BeautifulSoup(data, 'lxml')

lxml是一种解析器选项,即选择一个解析器。

标签选择:(在html中选择特定的内容)

1
2
3
4
5
6
7
soup.find('p').text
# 输出:——在云端,寻找我的星匙。
article = soup.find('article', class_="post post-type-normal").find("p")
print(article)
# 输出:<p>本文主要研究 zCore 的全貌和部分功能细节。</p>
print(article.text)
# 输出:本文主要研究 zCore 的全貌和部分功能细节。
url处理

主要是绝对路径和相对路径的url拼接。

这样可以保证拼接的url的正确性。

见:https://blog.csdn.net/qq_40134903/article/details/80646230

使用方法:

1
urljoin(A, B)
文件读写
1
2
3
file = open("data/blog.txt", 'w', encoding='utf-8')
print(article.text, file=file)
file.close()
反爬机制的处理 User-Agent

之前提到该网站具有一定的反爬机制。我也猜测到这与某种基于规则的识别相关。果然,rcy dalao讲到,这与User-Agent直接相关。

查看不做处理直接爬取时的User-Agent:(封IP)

1
2
3
response = get(url)
print(response.request.headers)
# {'User-Agent': 'python-requests/2.24.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}

绕过反爬机制的方式也很简单,直接从参数端覆盖输入真实访问时的User-Agent。这样便绕过了特征拦截。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def second():
url = "http://wjw.beijing.gov.cn/xwzx_20031/xwfb/"
UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36"
response = get(url, headers={"User-Agent": UA})
data = response.text
soup = BeautifulSoup(data, 'lxml')
ctx = soup.find('div', class_="weinei_left_con_line_text")
print(ctx)
news = ctx.find('a')
title = ctx['title']
file = open("data/bjwjw.txt", 'w', encoding='utf-8')
print(news.text, file=file)
print(title.text, file=file)
file.close()

或者直接获取title

1
2
title = news['title']
print(title, file=file)
最终效果

在加入一些对字典、集合的循环处理以后,获得了新闻的结构化数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def second():
url = "http://wjw.beijing.gov.cn/xwzx_20031/xwfb/"
UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36"
response = get(url, headers={"User-Agent": UA})
data = response.text
soup = BeautifulSoup(data, 'lxml')
ctx = soup.findAll('div', class_="weinei_left_con_line_text")
output = ""
for ele in ctx:
news = ele.find('a')
title, address = news['title'], news['href']
file = open("data/bjwjw.txt", 'w', encoding='utf-8')
output += title + "\t" + urljoin(url, address) + "\n"
print(output, file=file)
file.close()

正则表达式

形式语言和自动机中会涉及到正则相关的内容。

正则表达式对更加泛化的HTML查找更加有效,比如含有JS脚本的数据爬取。

这部分暂时不好复现,从讲课视频中截了个图: