任务:
-
学习get与post请求,尝试使用requests或者是urllib用get方法向https://www.baidu.com/发出一个请求,并将其返回结果输出。
-
如果是断开了网络,再发出申请,结果又是什么。了解申请返回的状态码。
-
了解什么是请求头,如何添加请求头。
-
学习什么是正则表达式并尝试一些正则表达式并进行匹配。
-
然后结合requests、re两者的内容爬取https://movie.douban.com/top250里的内容
-
要求抓取名次、影片名称、国家、导演等字段。
一些前期准备:
HTTP基本原理:
URL:URL正是使用 Web 浏览器等访问 Web 页面时需要输入的网页地址,中文叫统一资源定位符
如:https://blog.csdn.net/behrends。https是协议名,blog.csdn.net 是服务地址,behrends则是文件路径
URI全称为统一资源标识符。URL是是URI的子集
解:
任务一:
import requests
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
resp = requests.get('https://www.baidu.com',headers=headers)
print(resp.text) # 打印出网页源代码
print(resp.status_code) # 打印出状态调用status属性可以返回结果的状态码。
结果:
<!DOCTYPE html>
<!--STATUS OK-->
1.请求方法:
常见的请求方法有get和post
get和post的区别:
1.get是从服务器上获取数据,get请求参数包含在URL里面,数据可以在URL中看到,post是向服务器传送数据,因此get安全性非常低,post安全性较高。但是执行效率却比Post方法好
2.get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。在进行文件上传时只能使用post而不能是get。
任务二:
如果把网关了就会出现 11001的报错。:
常见的状态码:200成功,404页面未知道,500服务器内部错误
ConnectionError: HTTPSConnectionPool(host='www.baidu.com', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x0000024559833E80>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed',))
任务三:
请求头,用来说明服务器要使用附加信息,比较重要的信息有,比如cookie,referer,user-agent等
http请求头,HTTP客户程序(例如浏览器),向服务器发送请求的时候必须指明请求类型(一般是GET或者POST)。如有必要,客户程序还可以选择发送其他的请求头。
请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息,典型的请求头有:
- User-Agent:产生请求的浏览器类型。
- Accept:客户端可识别的内容类型列表。
- Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。
任务四:
叫正则表达式,是因为它们可以识别正则字符串(regular string)
常用的正则表达式符号:
符号 | 含义 | 例子 | 匹配结果 |
---|---|---|---|
* | 匹配前面的的字符、子表达式或括号内的字符0次或多次 | a*b* | aaaaa,aabbbb,bbbbbb |
+ | 匹配前面的的字符、子表达式或括号内的字符至少一次 | a+b+ | aaaaaab,aabbbbb,abbbbb |
[] | 匹配任意一个字符(相当于“任选一个”) | [A-Z]* | APPLE,PYTHON HTML |
() | 表达式编组(在正则表达式的规则里编组会优先 运行 | (a*b)* | aaabaab,abaaab, ababaaaaab |
{m,n} | 匹配前面的字符、子表达式或括号里的字符 m 到 n 次(包含 m 或 n) | a{2,3}b{2,3} | aabbb,aaabbb,aabb |
[^] | 匹配任意一个不在中括号里的字符 | [^A-Z]* | apple python |
| | 匹配任意一个由竖线分割的字符、子表达式(注 意是竖线,不是大字字母 I) | b(a|i|e)d | bad,bid,bed |
. | 匹配任意单个字符(包括符号、数字和空格等) | b.d | bad,bzd,b$d,b d |
^ | 指字符串开始位置的字符或子表达式 | ^a | apple,asdf,a |
\ | 转义字符(把有特殊含义的字符转换成字面形式) | \.\ | \\ | . | \ |
$ | 经常用在正则表达式的末尾,表示“从字符串的 末端匹配”。如果不用它,每个正则表达式实际都 带着“.*”模式,只会从字符串开头进行匹配。这 个符号可以看成是 ^ 符号的反义词 | [A-Z]*[a-z]*$ | ABCabc,zzzyx,Bob |
?! | “不包含”。这个奇怪的组合通常放在字符或正则 表达式前面,表示字符不能出现在目标字符串里。 这个符号比较难用,字符通常会在字符串的不同 部位出现。如果要在整个字符串中全部排除某个 字符,就加上 ^ 和 $ 符号 | ^((?![A-Z]).)*$ | no-caps-here,$ymb0ls a4e f!ne |
因此对于邮箱来说:正则表达式是:[A-Za-z0-9\._+]+@[A-Za-z]+\.(com|org|edu|net)
任务五:
import requests
import re
for i in range(10):
url='https://movie.douban.com/top250?start='+str(i*25)#翻页循环设置:通过对start赋值以25的倍数
html=requests.get(url).text
regex='<em class="">(\d+)</em>.*?<span class="title">(.*?)</span>.*?<p class="">(.*?)</p>.*?<span class="rating_num" property="v:average">(.*?)</span>.*?<span>(.*?)</span>.*?<span class="inq">(.*?)</span>'
pattern=re.compile(regex,re.S)
results=re.findall(pattern,html)
print(results)
参考文章:https://blog.csdn.net/qq_38243583/article/details/83186780
结果是:
[('1', '肖申克的救赎', '\n 导演: 弗兰克·德拉邦特 Frank Darabont 主演: 蒂姆·罗宾斯 Tim Robbins /...<br>\n 1994 / 美国 / 犯罪 剧情\n ', '9.6', '1418723人评价', '希望让人自由。'),
这样虽然得到了想要的结果,但是得到的数据比较杂乱,将匹配结果进一步进行处理,这里对"描述“里面的特殊字符 和<br>进行处理,利用re模块的sub函数将其替换为空字符串 将得到的新的描述以及爬取到的其他内容信息存储到dict字典当中去。导入json库,将字典内容保存到txt文本中。
import requests
import re
import json
for i in range(11):
url='https://movie.douban.com/top250?start='+str(i*25)#翻页循环设置:通过对start赋值以25的倍数
html=requests.get(url).text
regex='<em class="">(\d+)</em>.*?<span class="title">(.*?)</span>.*?<p class="">(.*?)</p>.*?<span class="rating_num" property="v:average">(.*?)</span>.*?<span>(.*?)</span>.*?<span class="inq">(.*?)</span>'
pattern=re.compile(regex,re.S)
results=re.findall(pattern,html)
#对得到的list列表进行处理
for item in results:
content=""
for every_list in item[2].split():
content=content+"".join(every_list)
content=re.sub(' ',' ',content)
content=re.sub('<br>', '', content)
print(content)
#将获取到的信息存储到字典中
dict={
"number":item[0],
"name":item[1],
"describe":content,
"star":item[3],
"evaluate":item[4],
"title":item[5]
}
with open('豆瓣top250.txt','a',encoding='utf-8') as f:
f.write(json.dumps(dict,ensure_ascii=False)+'\n')
打开txt: