宗旨:网站即是API
0. 准备工作
1. robots 协议
爬取网站一定要遵守robots.txt,否则会有法律风险(面向监狱编程)。在网站的域名后加 /robots.txt 可以看到其对爬虫的限制。比如:
百度:https://www.baidu.com/robots.txt
B站:https://www.bilibili.com/robots.txt
帝国理工:http://www.imperial.ac.uk/robots.txt
2. 安装python环境——Anaconda傻瓜式安装
3. 安装库文件:pip install requests 装完后运行以下代码测试:
import requests
r = requests.get("http://www.baidu.com/")
r.raise_for_status()
print(r.status_code) #HTTP 状态码
r.encoding = "utf-8"
print(r.text) #打印网站内容
4. 安装HTML解析库:pip install beautifulsoup4 装完后运行以下代码测试:
import requests
from bs4 import BeautifulSoup
url = "https://python123.io/ws/demo.html"
pa = {'User-Agent': 'Mozilla/5.0'}
r = requests.get(url, headers = pa)
r.raise_for_status()
r.encoding = r.apparent_encoding
demo = r.text
soup = BeautifulSoup(demo,"html.parser")
print(soup.prettify())
5. 安装 scrapy 框架:pip install scrapy
若报超时错误,更换为国内源即可,代码如下:pip install scrapy -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
安装完成后,在命令行运行 scrapy -h 测试。
6. 了解生成器——yield
def gen(n):
for i in range(n):
yield i**2
for i in gen(6):
print(i,end = " ")
#[out]: 0 1 4 9 16 25
生成器的优势:
- 更节省储存空间
- 响应更迅速
- 使用更灵活
1. requests库
0. requests库的7个主要方法
除去第一个,其余的与HTTP请求相对应
- requests.request():构造一个请求,支撑以下各方法的基础方法
- requests.get():获取HTML网页的主要方法
- requests.head():获取HTML网页的头部信息
- requests.post():向HTML网页提交POST请求
- requests.put():向HTML网页提交PUT请求
- requests.patch():向HTML网页提交局部修改请求
- requests.delete():向HTML网页提交删除请求
1. requests.get("url")
r = requests.get("url")
返回Response对像(即上面代码中的r)的属性:
r.status_code:HTTP请求的返回状态;详情点这里r.text:HTTP响应内容的字符串形式——url对应的页面内容r.encoding:响应内容的编码方式(header中分析出)r.apparent_enconding:备选编码方式(内容中分析出)r.content:响应内容的二进制形式
当 r.encoding 不能正确编码时,尝试使用 r.apparent_enconding 的编码方式
爬取网页的通用代码框架:
import requests
def getHTMLText(url):
try:
r = requests.get(url)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return "ERROR--getHTMLText"
if __name__ == "__main__":
url = "http://www.baidu.com/"
print(getHTMLText(url))
2. requests实战
1. 爬取京东商品页面
要修改HTTP请求的headers信息,变成浏览器访问。可以把以下代码放进一个函数,方便使用
import requests
url = "https://item.jd.com/100008771796.html"
kv = {'User-Agent': 'Mozilla/5.0'}
try:
r = requests.get(url, headers = kv)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.text[:1000])
except:
print(r.request.headers)
print(r.status_code)
print("ERROR--getHTMLText")
2. 百度搜索关键词提交
import requests
url = "http://www.baidu.com/s"
pa = {'User-Agent': 'Mozilla/5.0'}
kv = {'wd': 'python'}
try:
r = requests.get(url, headers = pa, params = kv)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.text[:1500])
print(r.request.headers)
except:
print(r.request.headers)
print(r.status_code)
print("ERROR--getHTMLText")
3. 网络图片的爬取和储存(也可以是视频和gif)
import requests
url = "https://car3.autoimg.cn/cardfs/product/g30/M00/96/DF/1024x0_1_q95_autohomecar__ChsEf16Qj0CAZge6AA0PAzXq4SI349.jpg"
path = "C:/Users/Ran/Desktop/abc.jpg" #文件储存路径+文件名+文件格式
r = requests.get(url)
print(r.status_code)
with open(path,'wb') as f:
f.write(r.content)
4. IP归属地查询
查询IP地址的网站的url会时常更新,以下代码可能失效。若不成功,更换最新的url即可。
import requests
url = "https://www.ip138.com/iplookup.asp?ip="
ip = "117.157.165.230"
url += ip
url += "&action=2"
pa = {'User-Agent': 'Mozilla/5.0'}
r = requests.get(url, headers = pa)
print(r.status_code)
r.encoding = r.apparent_encoding
print(r.text)
3. BeautifulSoup 库
1. 有4种解析器,最常用的是 ‘html.parser’。其他三种需要安装对应的库
在运行本小节其他代码前,请先运行以下代码,然后复制其他代码到命令窗口运行,或者将其他代码复制到这段代码下运行整个程序。
import requests
from bs4 import BeautifulSoup
url = "https://python123.io/ws/demo.html"
pa = {'User-Agent': 'Mozilla/5.0'}
r = requests.get(url, headers = pa)
r.raise_for_status()
r.encoding = r.apparent_encoding
demo = r.text
soup = BeautifulSoup(demo,"html.parser")
2. 5种基本元素
- Tag:标签——最基本的信息组织单位;以<>开头,以</>结尾
- Name:标签的名字;<p>...</p>的名字是‘p’,格式:<tag>.name
- Attributes:标签的属性;以字典形式组织,格式:<tag>.attrs
- NavigableString:标签内非字符串的属性;<>...</>中的字符,格式:<tag>.string
- Comment:标签内字符串的注释部分,一种特殊的comment类型
soup.title
Out[33]: <title>This is a python demo page</title>
tag = soup.a
print(tag)
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>
soup.a.name
Out[36]: 'a'
soup.a.parent.name
Out[37]: 'p'
soup.a.parent.parent.name
Out[38]: 'body'
soup.a.parent.parent.parent.name
Out[39]: 'html'
tag.attrs
Out[40]:
{'href': 'http://www.icourse163.org/course/BIT-268001',
'class': ['py1'],
'id': 'link1'}
tag.attrs['id']
Out[41]: 'link1'
type(tag)
Out[42]: bs4.element.Tag
tag.string
Out[43]: 'Basic Python'
soup.p.string
Out[44]: 'The demo python introduces several python courses.'
3. HTML文件遍历方法
标签树的下行遍历
- .contents:返回子节点的列表,将<tag>所有子节点存入列表
- .children:子节点的迭代类型,与 .contents 类似,用于循环编译子节点
- .descendants:子孙节点的迭代类型,包含所有子孙节点,用于循环遍历
for child in soup.body.children:
print(child)
标签树的上行遍历
- .parent:节点的父亲标签
- .parents:节点先辈标签的迭代类型,用于循环遍历先辈节点
for parent in soup.a.parents:
if parent is None:
print(parent)
else:
print(parent.name)
标签书的平行遍历
- .next_sibling:返回下一个平行节点的标签
- .previous_sibling:返回上一个平行节点的标签
- .next_siblings:迭代类型,返回之后所有的平行节点的标签
- .previous_siblings:迭代类型,返回之前所有的平行节点的标签
平行遍历必须在同一父节点下的各节点之间
soup.a.next_sibling
Out[56]: ' and '
soup.a.next_sibling.next_sibling
Out[57]: <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>
soup.a.previous_sibling
Out[58]: 'Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:\r\n'
for sibling in soup.a.next_siblings:
print(sibling.name)
None
a
None
4. 让 HTML 的内容更友好的显示
.prettify()
print(soup.a.prettify())
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">
Basic Python
</a>
5. 信息提取的一般方法
<>.find_all(name, attrs, recursive, string, **kwargs)——以列表的形式返回查找的结果
- name:对标签名称的检索字符串
- attrs:对标签属性值的检索字符串
- recursive:是否对子孙全部检索(默认为True)
- string:<>...</>中字符串区域的检索字符串
以下代码在console中运行
import re #正则表达式库
for tag in soup.find_all(re.compile('b')):
print(tag.name)
Out[4]:
body
b
soup.find_all(id=re.compile('link'))
Out[5]:
[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>,
<a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>]
soup.find_all(string = re.compile('python'))
Out[6]:
['This is a python demo page',
'The demo python introduces several python courses.']
简写/等价
- <tag>(...) == <tag>.find_all(...)
- soup.(...) == soup.find_all(...)
.find() 还有7中扩展用法,这里就不一一列出了。



Comments | 1 条评论
我来试试看能不能发评论