赞
踩
大家可以用此文来作为一个引导,文中的代码直接复制去python的IDE(比如pycharm或者spider)中就可以运行(需要先安装相应的python库)。小机灵鬼们要仔细学下去的话,文中会有一些链接,当然也可以自行百度/Google,或者买一本书来慢慢看
有一些是我在其他教程里面踩过的坑,比如用老方法(直接用cookie)已经不能模拟登录知乎了QAQ
文中有些链接可能需要翻墙哦
要用爬虫从网站上抓取信息,要先知道网站的构成和搭建方法
网页构成:
HTML - 定义网页的结构
css - 定义外观
js - 实现各种实时、动态、交互的页面功能
我们可以在pycharm中新建html和css文件,然后搭建自己的网站。
关于python:推荐使用pycharm + anaconda
参考资料:
Python:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000
Html 教程:http://www.w3school.com.cn/html/index.asp
Css 教程:http://www.w3school.com.cn/css/index.asp
JS 教程:http://www.w3school.com.cn/b.asp
或者:https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000
不一定要都看完才往下学,可以只看前面一点点,需要的时候再查阅(是个正常人都不会有兴趣全部看完的)
中文官方文档:http://cn.python-requests.org/zh_CN/latest/
当然还有英文的:http://www.python-requests.org/en/master/
requests快速上手:http://docs.python-requests.org/zh_CN/latest/user/quickstart.html
pip install requests
方法 | 用途 |
---|---|
requests.get(url, params, **kwargs) | 获取HTML网页的主要方法。其中params作为url中的额外参数,用于生成更具体的链接;**kwargs为访问控制参数 |
requests.head() | 获取网页头信息 |
requests.post() | 在网页原有基础上提交新内容 |
requests.put() | 覆盖原有内容 |
requests.patch() | 修改局部内容 |
requests.delete() | 删除各种内容 |
返回response对象
r = requests.xxx(...)
属性 | 内容 |
---|---|
r.status_code | HTTP请求的返回状态,200代表访问成功,404代表失败 |
r.text | HTTP响应内容的字符串形式 |
r.encoding | 从HTTP head标签中获取的响应内容的编码方式 |
r.apparent.encoding | 从具体响应内容分析出的编码方式 |
r.content | HTTP响应内容的二进制形式 |
r.cookies | |
r.headers |
输出r.text前,最好先运行语句:
r.encoding = r.apparent.encoding
以避免出现乱码
基本请求(六种)
文件上传
Cookies登录,回话维持
代理设置
身份认证
异常 | 说明 |
---|---|
requests.ConnectionError | 网络连接错误异常,如DNS查询失败,拒绝连接等 |
requests.HTTPError | HTTP错误异常,即状态码不等于200时 |
requests.Timeout | 请求URL超时 |
requests.TooManyRedirects | 重定向次数太多 |
requests.ConnectTimeout | 连接远程服务器超时异常 |
requests.URLRequired | 缺少URL |
用于处理程序正常执行过程中出现的一些异常情况,如语法错误、数据除零错误。
一般用来作为爬虫的代码框架,例子:
import requests # 判断状态码异常 def getHTML(url): try: r = requests.get(url, timeout=30) r.raise_for_status() # 状态码不等于200时返回1,并跳转到except r.encoding = r.apparent_encoding # 使输出的r.text中不会出现乱码 return r.text except: return "产生状态码异常" url1 = 'http://www.baidu.com' url2 = 'www.baidu.com' print(getHTML(url1)) print(getHTML(url2))
文件上传
import requests
# 上传一个文件,首先自行创建一个test.txt
file = {'file': open('test.txt', 'rb')}
r = requests.post("https://httpbin.org/post", files=file) # 该网站是一个适合学习爬虫的测试网站
print(r.text)
获取cookies
import requests
r = requests.get('http://www.baidu.com')
print(r.cookies)
print('\n')
print(type(r.cookies))
print('\n')
for key, value in r.cookies.items(): #items()方法将其转化为元组组成的列表
print(key, value)
会话维持
import requests
# 利用session,请求测试网址https://httpbin.org/cookies/set/number/123,
# 同时设置了一个cookie,名称为number,内容为123
s = requests.session()
s.get('https://httpbin.org/cookies/set/number/123')
r = s.get('https://httpbin.org/cookies')
print(r.text)
网络图片的下载与保存
打开百度图片,任选一张,右键,在新页面打开,复制图片URL
import requests
url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1542903064518&di=49abdd9985efa1e5e7795590c' \
'34781ce&imgtype=0&src=http%3A%2F%2Fpic3.zhimg.com%2Fv2-3afcf01edb3403f00efd5e4dafa2815b_1200x500.jpg'
r = requests.get(url)
print(r.text[:1000]) # 输出很乱的东西,实际上是像素点变成了str
print(r.content[:1000]) # 输出16进制内容,代表像素点。结果前的b代表这是bytes类型的数据
with open('picture.png', 'wb') as f:
f.write(r.content)
用requests来模拟登录:
有兴趣的小机灵鬼可以百度一下新版知乎的模拟登录方法,旧版的单纯用cookie来模拟登录知乎的方法已经无效了。这里就不作展示了emmm我懒
使用get()方法中的params参数,获取百度对于某个关键词的搜索页面的源码。同时解决params中的中文编码问题。
import requests
url = 'http://www.baidu.com/s'
keyword = {'wd': '爬虫'.encode('gbk')}
try:
r = requests.get(url, params=keyword)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.text)
except:
print('获取源码失败')
可以在浏览器中打开百度,搜索 爬虫,然后对比代码输出的结果。
小规模网页爬虫:用requests方法获取网页
中规模网站爬虫:运用scrapy
大规模全网爬虫:多用于搜索引擎,要自己开发,没有第三方库。这就超出我的知识范围了
影响Web服务器性能
隐私泄露
来源审判:判断User-Agent进行限制
发布公告:Robots协议(Robots Exclusion Protocol),告知网络爬虫哪些页面可以抓取,哪些不可以
伪装成浏览器,爬取亚马逊网页
import requests
url = 'https://www.amazon.cn/dp/B07746N2J9'
header = {'user-agent': 'Mozilla/5.0'} # 用于伪装成浏览器
try:
r = requests.get(url, headers=header)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.text[:1000])
except:
print('获取网页失败')
正则表达式是一种特殊的字符串模式,用于匹配一组字符串,就好比用模具做产品,而正则表达式就是这个模具,定义一种规则去匹配符合规则的字符串。
参考资料:
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143193331387014ccd1040c814dee8b2164bb4f064cff000
http://www.runoob.com/regexp/regexp-tutorial.html
在线正则表达式测试:http://tool.oschina.net/regex# 在第一个框框中输入要测试的文本,然后在第二个框框输入正则表达式,或者点击右边的一列选项(接着就会出现写好的响应的表达式)
如果你的python环境中没有re库,请自行安装。
下面来看看常用的函数。
该方法尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回None;如果成功,就返回一个SRE_Match对象。
result = re.match(pattern, string, flags=0) # patter是正则表达式,string是要匹配的字符串
result.group()返回匹配的字符串,result.span()返回的是匹配到的字符串在原字符串中的位置范围。例子:
它在匹配时会扫描整个字符串,然后返回第一个成功匹配的结果。
扫描整个字符串,然后返回所有成功匹配的结果。
用于删掉字符串中的特定内容。
将正则字符串编译成正则表达式对象。
下面来看一下比较凶残的例子:
使用正则表达式,爬取猫眼电影-榜单-最受期待榜中的所有电影(http://maoyan.com/board/6?offset=0 )的信息,并输出到txt文件:
import requests # 下面这些python库请自行安装 import re import json import time # 爬取单一网页 def get_one_page(url): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) ' # 伪装成浏览器 'Chrome/63.0.3239.132 Safari/537.36' } r = requests.get(url, headers=headers) if r.status_code == 200: return r.text return None # 提取单一网页的关键信息 def parse_one_page(html): # 使用正则表达式提取关键内容 pattern = re.compile('<dd.*?board-index.*?">(\d+)</i.*?data-src="(.*?)".*?<p class="name"><a.*?>(.*?)</a>.*' '?<p class="star">(.*?)</p.*?class="releasetime">(.*?)</p.*?</dd>', re.S) # 第二个参数为re.S,作用是使得 . 可以匹配换行符 items = re.findall(pattern, html) result = [] for item in items: result.append({ '排名': item[0], '海报': item[1], '电影名称': item[2], '主演': item[3].strip()[3:] if len(item[3]) > 3 else '', '上映时间': item[4].strip()[5:] if len(item[4]) > 5 else '' }) return result # 写进txt文件 def write_to_file(content): with open('result2.txt', 'a', encoding='utf-8') as f: # print(type(json.dumps(content))) # 先将content转换为字符串格式,然后再写入文件 f.write(json.dumps(content, ensure_ascii=False) + '\n') def main(offset): url = 'http://maoyan.com/board/6?offset=' + str(offset) html = get_one_page(url) for item in parse_one_page(html): print(item) write_to_file(item) if __name__ == '__main__': # 因为每一页只有10部电影,所以需要循环提取 for i in range(10): main(offset=i * 5) # 访问完每页后停一小会,对应反爬虫机制 time.sleep(1) # 前五条输出: # {'排名': '1', '海报': 'http://p1.meituan.net/movie/c7453592d38b7aff6a774a52732792cd3778866.jpg@160w_220h_1e_1c', '电影名称': '人间·喜剧', '主演': '艾伦,王智,鲁诺', '上映时间': '2018-12-07'} # {'排名': '2', '海报': 'http://p0.meituan.net/movie/c304c687e287c7c2f9e22cf78257872d277201.jpg@160w_220h_1e_1c', '电影名称': '龙猫', '主演': '秦岚,糸井重里,岛本须美', '上映时间': '2018-12-14'} # {'排名': '3', '海报': 'http://p0.meituan.net/movie/e5f0a55327d5be1caa9f110abcca23865841112.jpg@160w_220h_1e_1c', '电影名称': '飞驰人生', '主演': '沈腾,黄景瑜,尹正', '上映时间': '2019-02-05'} # {'排名': '4', '海报': 'http://p1.meituan.net/movie/9cd36871e75c756f3ad175afa6452cf2177292.jpg@160w_220h_1e_1c', '电影名称': '疯狂的外星人', '主演': '黄渤,沈腾,马修·莫里森', '上映时间': '2019-02-05'} # {'排名': '5', '海报': 'http://p1.meituan.net/movie/c57e3e283679ab6efab23b16a2d20364838623.jpg@160w_220h_1e_1c', '电影名称': '情圣2', '主演': '吴秀波,白百何,肖央', '上映时间': '2019-02-05'}
前面介绍了使用正则表达式来提取内容的方法,但是一大堆正则表达式,看着就想杀人
于是,可爱的程序猿们开发出了各种解析工具。鼓掌.jpg
Beautiful Soup是Python的一个HTML或XML的解析库,可以用来方便地提取我们想要的网页内容。
Beautiful Soup在解析时实际上依赖解析器,它支持一下四种解析器:
解析器 | 使用方法 | advantage | 坑爹的地方 |
---|---|---|---|
Python标准库 | BeautifulSoup(markup, “html.parser”) | Python内置 | Python 2.7.3 or 3.2.2 前 的版本中文档容错能力差 |
lxml HTML解析器 | BeautifulSoup(markup, “lxml”) | 速度快 | 需要安装lxml |
lxml XML解析器 | BeautifulSoup(markup, “xml”) | 速度快ÿ |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。