Python 爬虫初探
准备部分
0x01 爬虫的简介和价值
a. 简介
自动抓取互联网数据的程序,是基础技术之一
b. 价值
快速提取网络中有价值的信息
0x02 爬虫的开发环境
a. 环境清单
- Python3.7
- 开发环境:Mac、Windows、Linux
- 编辑器:Pycharm
- 网页下载:requests(2.21.0)
- 网页解析:BeautifulSoup/bs4(4.11.2)
- 动态网页下载:Selenium(3.141.0)
b. 环境测试
新建一个 Python 软件包,命名为 test
在上述软件包中新建一个 Python 文件,命名为 test_env
测试代码如下
import requests
from bs4 import BeautifulSoup
import selenium print("OK!")
如果成功输入
OK!
则说明测模块安装成功
基础部分
0x03 简单的爬虫架构和执行流程
爬虫调度端(启动、停止)
爬虫架构(三大模块)
graph LR
A(URL 管理器)--URL-->B(网页下载器)
B--HTML-->C(网页解析器)
C-.URL.->AURL 管理器
URL 对管理,防止重复爬取
网页下载器
网页内容下载
网页解析器
提取价值数据,提取新的待爬 URL
价值数据
0x04 URL 管理器
a. 介绍
- 作用:对爬取的 URL 进行管理,防止重复和循环爬取
- 对外接口
- 取出一个待爬取的 URL
- 新增待爬取的 URL
- 实现逻辑
- 取出时状态变成已爬取
- 新增时判断是否已存在
- 数据存储
- Python 内存
- 待爬取 URL 集合:set
- 已爬取 URL 集合:set
- redis
- 待爬取 URL 集合:set
- 已爬取 URL 集合:set
- MySQL
urls(url, is_crawled)
- Python 内存
b. 代码实现
新建一个 Python 软件包,命名为 utils
在上述软件包中新建一个 Python 文件,命名为 url_manager
由于需要对外暴露接口,需要封装成类,代码如下:
class UrlManager():
"""
url 管理器
""" # 初始化函数
def __init__(self):
self.new_urls = set()
self.old_urls = set() # 新增 URL
def add_new_url(self, url):
# 判空
if url is None or len(url) == 0:
return
# 判重
if url is self.new_urls or url in self.old_urls:
return
# 添加
self.new_urls.add(url) # 批量添加 URL
def add_new_urls(self, urls):
if urls is None or len(urls) == 0:
return
for url in urls:
self.add_new_url(url) # 获取一个新的待爬取 URL
def get_url(self):
if self.has_new_url():
url = self.new_urls.pop()
self.old_urls.add(url)
return url
else:
return None # 判断是否有新的待爬取的 URL
def has_new_url(self):
return len(self.new_urls) > 0 # 测试代码
if __name__ == "__main__":
url_manager = UrlManager() # URL 添加测试
url_manager.add_new_url("url1")
url_manager.add_new_urls(["url1", "url2"])
print(url_manager.new_urls, url_manager.old_urls) # URL 获取测试
print("=" * 20) # 分割线
new_url = url_manager.get_url()
print(url_manager.new_urls, url_manager.old_urls) print("=" * 20)
new_url = url_manager.get_url()
print(url_manager.new_urls, url_manager.old_urls) print("=" * 20)
print(url_manager.has_new_url())
0x05 网页下载器(requests)
a. 介绍
安装:
pip install requests
介绍:
Requests is an elegant and simple HTTP library for Python, built for human beings.
Requests 是一个优雅的、简单的 Python HTTP 库,常常用于爬虫中对网页内容的下载
执行流程
graph LR
A(Python程序<br/>requests 库)--request-->B(网页服务器)
B--respone-->A
b. 发送 request 请求
request.get/post(url, params, data, headers, timeout, verify, allow_redirects, cookies)
url
:要下载的目标网页的 URLparams
:字典形式,设置 URL 后面的参数,如:?id=123&name=xxx
data
:字典或者字符串,一般用于使用 POST 方法时提交数据headers
:设置user-agent
、refer
等请求头timeout
:超时时间,单位是秒verify
:布尔值,是否进行 HTTPS 证书认证,默认 True,需要自己设置证书地址allow_redirects
:布尔值,是否让 requests 做重定向处理,默认 Truecookies
:附带本地的 cookies 数据url
、data
、headers
、timeout
为常用参数
c. 接收 response 响应
res = requests.get/post(url)
res.status_code
:查看状态码res.encoding
:查看当前编码以及变更编码(requests 会根据请求头推测编码,推测失败则采用ISO-8859-1进行编码)
res.text
:查看返回的网页内容res.headers
:查看返回的 HTTP 的 Headersres.url
:查看实际访问的 URLres.content
:以字节的方式返回内容,比如下载图片时res.cookies
:服务端要写入本地的 cookies 数据
d. 使用演示
在 cmd 中安装 ipython,命令为:
python -m pip install ipython
在 cmd 中启动 ipython,命令为:ipython
In [1]: import requests
In [2]: url = "https://www.cnblogs.com/SRIGT"
In [3]: res = requests.get(url)
In [4]: res.status_code
Out[4]: 200
In [5]: res.encoding
Out[5]: 'utf-8'
In [6]: res.url
Out[6]: 'https://www.cnblogs.com/SRIGT'
0x06 网页解析器(BeautifulSoup)
a. 介绍
网址:Beautiful Soup: We called him Tortoise because he taught us.
安装:
pip install beautifulsoup4
介绍:Python 第三方库,用于从 HTML 中提取数据
使用:
import bs4
或from bs4 import BeautifulSoup
b. 语法
HTML网页-->A(创建 BeautifulSoup 对象)
A-->B(搜索节点<br/>find_all, find)
B-.->B1(按节点名称)
B-.->B2(按节点属性值)
B-.->B3(按节点文字)
B-->C(访问节点<br/>名称, 属性, 文字)
创建 BeautifulSoup 对象
from bs4 import BeautifulSoup # 根据 HTML 网页字符串创建 BeautifulSoup 对象
soup = BeautifulSoup(
html_doc, # HTML 文档字符串
'html.parser', # HTML 解析器
from_encoding = 'utf-8' # HTML 文档的编码
)
搜索节点
# find_all(name, attrs, string)
# 查找所有标签为 a 的节点
soup.find_all('a') # 查找所有标签为 a,链接符合 /xxx/index.html 形式的节点
soup.find_all('a', href='/xxx/index.html') # 查找所有标签为 div,class 为 abc,文字为 python 的节点
soup.find_all('div', class_='abc', string='python')
访问节点信息
# 得到节点: <a href='1.html'>Python</a>
# 获取查找到的节点的标签名称
node.name
# 获取查找到的 a 节点的 href 属性
node['href']
# 获取查找到的 a 节点的链接文字
node.get_text()
c. 使用演示
目标网页
<html>
<head>
<meta charset="utf-8">
<title>页面标题</title>
</head>
<body>
<h1>标题一</h1>
<h2>标题二</h2>
<h3>标题一</h3>
<h4>标题一</h4>
<div id="content" class="default">
<p>段落</p>
<a href="http://www.baidu.com">百度</a>
<a href="http://www.cnblogs.com/SRIGT">我的博客</a>
</div>
</body>
</html>
测试代码
from bs4 import BeautifulSoup with open("./test.html", 'r', encoding='utf-8') as fin:
html_doc = fin.read() soup = BeautifulSoup(html_doc, "html.parser")
div_node = soup.find("div", id="content")
print(div_node)
print() links = div_node.find_all("a")
for link in links:
print(link.name, link["href"], link.get_text()) img = div_node.find("img")
print(img["src"])
实战部分
0x07 简单案例
url = "http://www.crazyant.net/"
import requests
r = requests.get(url)
if r.status_code != 200:
raise Exception()
html_doc = r.text
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, "html.parser")
h2_nodes = soup.find_all("h2", class_="entry-title")
for h2_node in h2_nodes:
link = h2_node.find("a")
print(link["href"], link.get_text())
0x08 爬取所有博客页面
- 根域名:蚂蚁学Python
- 文章页 URL 形式:PyCharm开发PySpark程序的配置和实例 – 蚂蚁学Python
requests 请求时附带 cookie 字典
import requests
cookies = {
"captchaKey": "14a54079a1",
"captchaExpire": "1548852352"
}
r = requests.get(
"http://url",
cookies = cookies
)
正则表达式实现模糊匹配
url1 = "http://www.crazyant.net/123.html"
url2 = "http://www.crazyant.net/123.html#comments"
url3 = "http://www.baidu.com" import re
pattern = r'^http://www.crazyant.net/\d+.html$' print(re.match(pattern, url1))
print(re.match(pattern, url2))
print(re.match(pattern, url3))
全页面爬取
from utils import url_manager
from bs4 import BeautifulSoup
import requests
import re root_url = "http://www.crazyant.net" urls = url_manager.UrlManager()
urls.add_new_url(root_url) file = open("craw_all_pages.txt", "w")
while urls.has_new_url():
curr_url = urls.get_url()
r = requests.get(curr_url, timeout=3)
if r.status_code != 200:
print("error, return status_code is not 200", curr_url)
continue
soup = BeautifulSoup(r.text, "html.parser")
title = soup.title.string file.write("%s\t%s\n" % (curr_url, title))
file.flush()
print("success: %s, %s, %d" % (curr_url, title, len(urls.new_urls))) links = soup.find_all("a")
for link in links:
href = link.get("href")
if href is None:
continue
pattern = r'^http://www.crazyant.net/\d+.html$'
if re.match(pattern, href):
urls.add_new_url(href) file.close()
0x09 爬取豆瓣电影Top250
目前该榜单设置了反爬
步骤:
- 使用 requests 爬取网页
- 使用 BeautifulSoup 实现数据解析
- 借助 pandas 将数据写到 Excel
调用
import requests
from bs4 import BeautifulSoup
import pandas as pd
下载共 10 个页面的 HTML
# 构造分页数字列表
page_indexs = range(0, 250, 25)
list(page_indexs) def download_all_htmls():
"""
下载所有列表页面的 HTML,用于后续的分析
"""
htmls = []
for idx in page_indexs:
url = f"https://movie.douban.com/top250?start={idx}&filter="
print("craw html: ", url)
r = requests.get(url)
if r.status_code != 200:
raise Exception("error")
htmls.append(r.text)
return htmls # 执行爬取
htmls = download_all_htmls()
解析 HTML 得到数据
def parse_single_html(html):
"""
解析单个 HTML,得到数据
@return list({"link", "title", [label]})
"""
soup = BeautifulSoup(html, 'html.parser')
article_items = (
soup.find("div", class_="article")
.find("ol", class_="grid_view")
.find_all("div", class_="item")
)
datas = []
for article_item in article_items:
rank = article_item.find("div", class_="pic").find("em").get_text()
info = article_item.find("div", class_="info")
title = info.find("div", class_="hd").find("span", class_="title").get_text()
stars = (
info.find("div", class_="bd")
.find("div", class_="star")
.find_all("span")
)
rating_star = stars[0]["class"][0]
rating_num = stars[1].get_text()
comments = stars[3].get_text() datas.append({
"rank": rank,
"title": title,
"rating_star": rating_star.replace("rating", "").replace("-t", ""),
"rating_num": rating_num,
"comments": comments.replace("人评价", "")
})
return datas pprint.pprint(parse_single_html(htmls[0])) all_datas = []
for html in htmls:
all_datas.extend(parse_single_html(html)) print(all_datas)
将结果存入 Excel
df = pd.DataFrame(all_datas)
df.to_excel("TOP250.xlsx")
End
Python 爬虫初探的更多相关文章
- Python爬虫初探 - selenium+beautifulsoup4+chromedriver爬取需要登录的网页信息
目标 之前的自动答复机器人需要从一个内部网页上获取的消息用于回复一些问题,但是没有对应的查询api,于是想到了用脚本模拟浏览器访问网站爬取内容返回给用户.详细介绍了第一次探索python爬虫的坑. 准 ...
- Python爬虫系列 - 初探:爬取旅游评论
Python爬虫目前是基于requests包,下面是该包的文档,查一些资料还是比较方便. http://docs.python-requests.org/en/master/ POST发送内容格式 爬 ...
- 我的第一个 python 爬虫脚本
#!/usr/bin/env python# coding=utf-8import urllib2from bs4 import BeautifulSoup #res = urllib.urlopen ...
- Scrapy框架爬虫初探——中关村在线手机参数数据爬取
关于Scrapy如何安装部署的文章已经相当多了,但是网上实战的例子还不是很多,近来正好在学习该爬虫框架,就简单写了个Spider Demo来实践.作为硬件数码控,我选择了经常光顾的中关村在线的手机页面 ...
- Python 爬虫模拟登陆知乎
在之前写过一篇使用python爬虫爬取电影天堂资源的博客,重点是如何解析页面和提高爬虫的效率.由于电影天堂上的资源获取权限是所有人都一样的,所以不需要进行登录验证操作,写完那篇文章后又花了些时间研究了 ...
- python爬虫成长之路(一):抓取证券之星的股票数据
获取数据是数据分析中必不可少的一部分,而网络爬虫是是获取数据的一个重要渠道之一.鉴于此,我拾起了Python这把利器,开启了网络爬虫之路. 本篇使用的版本为python3.5,意在抓取证券之星上当天所 ...
- python爬虫学习(7) —— 爬取你的AC代码
上一篇文章中,我们介绍了python爬虫利器--requests,并且拿HDU做了小测试. 这篇文章,我们来爬取一下自己AC的代码. 1 确定ac代码对应的页面 如下图所示,我们一般情况可以通过该顺序 ...
- python爬虫学习(6) —— 神器 Requests
Requests 是使用 Apache2 Licensed 许可证的 HTTP 库.用 Python 编写,真正的为人类着想. Python 标准库中的 urllib2 模块提供了你所需要的大多数 H ...
- 批量下载小说网站上的小说(python爬虫)
随便说点什么 因为在学python,所有自然而然的就掉进了爬虫这个坑里,好吧,主要是因为我觉得爬虫比较酷,才入坑的. 想想看,你可以批量自动的采集互联网上海量的资料数据,是多么令人激动啊! 所以我就被 ...
- python 爬虫(二)
python 爬虫 Advanced HTML Parsing 1. 通过属性查找标签:基本上在每一个网站上都有stylesheets,针对于不同的标签会有不同的css类于之向对应在我们看到的标签可能 ...
随机推荐
- Docker的使用记录
开始 这是第一个尝试在Leanote上面编写文章,我觉得最重要的事情就是能够保证md文件是能够移植的,否则如果这个软件不靠谱的话,我还能把文章移动到别的地方去.所以先写一篇文章看看效果如何,方便不方便 ...
- C++ STL 容器-array类型
C++ STL 容器-array类型 array是C++11STL封装的数组,内存分配在栈中stack,绝对不会重新分配,随机访问 创建和初始化 // 下面的等同于int a[10]; std::ar ...
- Java Eclipse JUnit单元测试
1 package com.bytezreo.ut; 2 3 import org.junit.Test; 4 5 /** 6 * 7 * @Description Java中的JUnit单元测试 8 ...
- Java 练习题 5岁的狗按人的年龄计算的话,前两年每一年是人的 10.5岁,之后每一年 * 增加4岁。如果5岁的狗、相当于人的多少年龄 * 10.5 + 10.5 + 4 +4 +4=33岁
1 /*** 2 * 练习题 3 * 5岁的狗按人的年龄计算的话,前两年每一年是人的 10.5岁,之后每一年 4 * 增加4岁.如果5岁的狗.相当于人的多少年龄 5 * 10.5 + 10.5 + 4 ...
- npm包(npm install --legacy-bundling) 通过npm-pack-all 打包tgz,放到内网(不联网)nexus发布(npm publish)
npm包(npm install --legacy-bundling) 通过npm-pack-all 打包tgz,放到内网(不联网)nexus发布(npm publish) 需求 内网不联网,安装指定 ...
- StatefulSet是怎样实现的
StatefulSet是Kubernetes中用于管理有状态应用的标准实现.与Deployment不同,StatefulSet为每个Pod提供了一个唯一的.稳定的网络标识符,并且Pod的启动和停止顺序 ...
- c语言中float和double类型的区别
1.变量bai类型不同 float属于单du精度zhi型浮点数据. double属于双精度型浮点数据. 2.指数范围不同 float的指数范围为-127~128. double而double的指数范围 ...
- 前端开源项目UIRecorder录制脚本遇到的一些问题
D:\nodejs\node_global>uirecorder init __ ______ ____ __ / / / / _/ / __ \___ _________ _________/ ...
- 笔记:vite 的启动链路以及背后的部分原理
这里分享一篇找到的文章 原文地址:https://blog.csdn.net/frontend_frank/article/details/106632197 NO.1 vite 是什么 vite - ...
- cyc_to_led
Entity: cyc_to_led File: cyc_to_led.v Diagram Generics Generic name Type Value Description MD_SIM_AB ...