Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
风灵Erick
Python-100-Days
提交
2315b0ce
P
Python-100-Days
项目概览
风灵Erick
/
Python-100-Days
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Python-100-Days
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
2315b0ce
编写于
5月 29, 2018
作者:
骆昊的技术专栏
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
更新了爬虫第2天文档
上级
e86dece2
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
125 addition
and
44 deletion
+125
-44
Day66-75/02.数据采集和解析.md
Day66-75/02.数据采集和解析.md
+65
-0
Day66-75/code/example01.py
Day66-75/code/example01.py
+26
-17
Day66-75/code/example02.py
Day66-75/code/example02.py
+34
-27
未找到文件。
Day66-75/02.数据采集和解析.md
浏览文件 @
2315b0ce
## 数据采集和解析
通过上一个章节,我们已经了解到了开发一个爬虫需要做的工作以及一些常见的问题,至此我们可以对爬虫开发需要做的工作以及相关的技术做一个简单的汇总,可能有些库我们之前并没有使用过,不过别担心,这些内容我们都会讲到的。
1.
下载数据 - urllib / requests / aiohttp。
2.
解析数据 - re / lxml / beautifulsoup4(bs4)/ pyquery。
3.
持久化 - pymysql / redis / sqlalchemy / pymongo。
4.
调度器 - 进程 / 线程 / 协程。
### HTML页面分析
```
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>Hello, world!</h1>
<p>这是一个神奇的网站!</p>
<hr>
<div>
<h2>这是一个例子程序</h2>
<p>静夜思</p>
<p class="foo">床前明月光</p>
<p id="bar">疑似地上霜</p>
<p class="foo">举头望明月</p>
<div><a href="http://www.baidu.com"><p>低头思故乡</p></a></div>
</div>
<a class="foo" href="http://www.qq.com">腾讯网</a>
<img src="./img/pretty-girl.png" alt="美女">
<img src="./img/hellokitty.png" alt="凯蒂猫">
<img src="/static/img/pretty-girl.png" alt="美女">
<table>
<tr>
<th>姓名</th>
<th>上场时间</th>
<th>得分</th>
<th>篮板</th>
<th>助攻</th>
</tr>
</table>
</body>
</html>
```
如果你对上面的代码并不感到陌生,那么你一定知道HTML页面通常由三部分构成,分别是:用来承载内容的Tag(标签)、负责渲染页面的CSS(层叠样式表)以及控制交互式行为的JavaScript。通常,我们可以在浏览器的右键菜单中通过“查看网页源代码”的方式获取网页的代码并了解页面的结构;当然,我们也可以通过浏览器提供的开发人员工具来了解网页更多的信息。
#### 使用requests获取页面
1.
GET请求和POST请求。
2.
URL参数和请求头。
3.
复杂的POST请求(文件上传)。
4.
操作Cookie。
### 三种采集方式
#### 三种采集方式的比较
| 抓取方法 | 速度 | 使用难度 | 备注 |
| ---------- | --------------------- | -------- | ------------------------------------------ |
| 正则表达式 | 快 | 困难 | 常用正则表达式
<br>
在线正则表达式测试 |
| lxml | 快 | 一般 | 需要安装C语言依赖库
<br>
唯一支持XML的解析器 |
| Beautiful | 快/慢(取决于解析器) | 简单 | |
> 说明:Beautiful的解析器包括:Python标准库(html.parser)、lxml的HTML解析器、lxml的XML解析器和html5lib。
#### BeautifulSoup的使用
1.
遍历文档树。
2.
五种过滤器:字符串、正则表达式、列表、True、方法。
Day66-75/code/example01.py
浏览文件 @
2315b0ce
...
...
@@ -8,7 +8,8 @@ import ssl
from
pymysql
import
Error
def
decode_page
(
page_bytes
,
charsets
=
(
'utf-8'
,
)):
# 通过指定的字符集对页面进行解码(不是每个网站都将字符集设置为utf-8)
def
decode_page
(
page_bytes
,
charsets
=
(
'utf-8'
,)):
page_html
=
None
for
charset
in
charsets
:
try
:
...
...
@@ -20,7 +21,8 @@ def decode_page(page_bytes, charsets=('utf-8', )):
return
page_html
def
get_page_html
(
seed_url
,
*
,
retry_times
=
3
,
charsets
=
(
'utf-8'
,
)):
# 获取页面的HTML代码(通过递归实现指定次数的重试操作)
def
get_page_html
(
seed_url
,
*
,
retry_times
=
3
,
charsets
=
(
'utf-8'
,)):
page_html
=
None
try
:
page_html
=
decode_page
(
urlopen
(
seed_url
).
read
(),
charsets
)
...
...
@@ -32,32 +34,38 @@ def get_page_html(seed_url, *, retry_times=3, charsets=('utf-8', )):
return
page_html
# 从页面中提取需要的部分(通常是链接也可以通过正则表达式进行指定)
def
get_matched_parts
(
page_html
,
pattern_str
,
pattern_ignore_case
=
re
.
I
):
pattern_regex
=
re
.
compile
(
pattern_str
,
pattern_ignore_case
)
return
pattern_regex
.
findall
(
page_html
)
if
page_html
else
[]
def
start_crawl
(
seed_url
,
match_pattern
):
# 开始执行爬虫程序并对指定的数据进行持久化操作
def
start_crawl
(
seed_url
,
match_pattern
,
*
,
max_depth
=-
1
):
conn
=
pymysql
.
connect
(
host
=
'localhost'
,
port
=
3306
,
database
=
'crawler'
,
user
=
'root'
,
password
=
'123456'
,
charset
=
'utf8'
)
try
:
with
conn
.
cursor
()
as
cursor
:
url_list
=
[
seed_url
]
visited_url_list
=
{
seed_url
:
0
}
while
url_list
:
current_url
=
url_list
.
pop
(
0
)
page_html
=
get_page_html
(
current_url
,
charsets
=
(
'utf-8'
,
'gbk'
,
'gb2312'
))
links_list
=
get_matched_parts
(
page_html
,
match_pattern
)
url_list
+=
links_list
param_list
=
[]
for
link
in
links_list
:
page_html
=
get_page_html
(
link
,
charsets
=
(
'utf-8'
,
'gbk'
,
'gb2312'
))
headings
=
get_matched_parts
(
page_html
,
r
'<h1>(.*)<span'
)
if
headings
:
param_list
.
append
((
headings
[
0
],
link
))
cursor
.
executemany
(
'insert into tb_result values (default, %s, %s)'
,
param_list
)
conn
.
commit
()
depth
=
visited_url_list
[
current_url
]
if
depth
!=
max_depth
:
page_html
=
get_page_html
(
current_url
,
charsets
=
(
'utf-8'
,
'gbk'
,
'gb2312'
))
links_list
=
get_matched_parts
(
page_html
,
match_pattern
)
param_list
=
[]
for
link
in
links_list
:
if
link
not
in
visited_url_list
:
visited_url_list
[
link
]
=
depth
+
1
page_html
=
get_page_html
(
link
,
charsets
=
(
'utf-8'
,
'gbk'
,
'gb2312'
))
headings
=
get_matched_parts
(
page_html
,
r
'<h1>(.*)<span'
)
if
headings
:
param_list
.
append
((
headings
[
0
],
link
))
cursor
.
executemany
(
'insert into tb_result values (default, %s, %s)'
,
param_list
)
conn
.
commit
()
except
Error
:
pass
# logging.error('SQL:', error)
...
...
@@ -67,8 +75,9 @@ def start_crawl(seed_url, match_pattern):
def
main
():
ssl
.
_create_default_https_context
=
ssl
.
_create_unverified_context
start_crawl
(
'http://sports.sohu.com/nba_a.shtml'
,
r
'<a[^>]+test=a\s[^>]*href=["\'](.*?)["\']'
)
start_crawl
(
'http://sports.sohu.com/nba_a.shtml'
,
r
'<a[^>]+test=a\s[^>]*href=["\'](.*?)["\']'
,
max_depth
=
2
)
if
__name__
==
'__main__'
:
...
...
Day66-75/code/example02.py
浏览文件 @
2315b0ce
...
...
@@ -7,38 +7,45 @@ def main():
html
=
"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>Hello, world!</h1>
<p>Good!!!</p>
<hr>
<div>
<h2>这是一个例子程序</h2>
<p>静夜思</p>
<p class="foo">床前明月光</p>
<p id="bar">疑似地上霜</p>
<p class="foo">举头望明月</p>
<div><a href="http://www.baidu.com"><p>低头思故乡</p></a></div>
</div>
<a class="foo" href="http://www.qq.com">腾讯网</a>
<img src="./img/pretty-girl.png" alt="美女">
<img src="./img/hellokitty.png" alt="凯蒂猫">
<img src="./static/img/pretty-girl.png" alt="美女">
<goup>Hello, Goup!</goup>
</body>
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>Hello, world!</h1>
<p>这是一个神奇的网站!</p>
<hr>
<div>
<h2>这是一个例子程序</h2>
<p>静夜思</p>
<p class="foo">床前明月光</p>
<p id="bar">疑似地上霜</p>
<p class="foo">举头望明月</p>
<div><a href="http://www.baidu.com"><p>低头思故乡</p></a></div>
</div>
<a class="foo" href="http://www.qq.com">腾讯网</a>
<img src="./img/pretty-girl.png" alt="美女">
<img src="./img/hellokitty.png" alt="凯蒂猫">
<img src="/static/img/pretty-girl.png" alt="美女">
<table>
<tr>
<th>姓名</th>
<th>上场时间</th>
<th>得分</th>
<th>篮板</th>
<th>助攻</th>
</tr>
</table>
</body>
</html>
"""
# resp = requests.get('http://sports.sohu.com/nba_a.shtml')
# html = resp.content.decode('gbk')
soup
=
BeautifulSoup
(
html
,
'lxml'
)
# JavaScript - document.title
print
(
soup
.
title
)
# JavaScript: document.body.h1
# JavaScript: document.forms[0]
# JavaScript - document.body.h1
print
(
soup
.
body
.
h1
)
print
(
soup
.
find_all
(
re
.
compile
(
r
'p$'
)))
print
(
soup
.
find_all
(
re
.
compile
(
r
'^h'
)))
print
(
soup
.
find_all
(
re
.
compile
(
r
'r$'
)))
print
(
soup
.
find_all
(
'img'
,
{
'src'
:
re
.
compile
(
r
'\./img/\w+.png'
)}))
print
(
soup
.
find_all
(
lambda
x
:
len
(
x
.
attrs
)
==
2
))
print
(
soup
.
find_all
(
'p'
,
{
'class'
:
'foo'
}))
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录