这是教材上的一个实例,今天学的总结一下。
首先感谢一下同老师送滴书哼
顺便推一下这本书:《Python3网路爬虫开发实战》(崔庆才)
先给代码
Pycharm + py3.7 调过
不很长50行左右,爬一下猫眼top100的一些信息
from builtins import len, open, str, range
import json
import time
from requests.exceptions import RequestException
import requests
import re
def get_one_page(url):
try:
# 伪装请求头改为Chrome
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chome/65.0.3325.162 Safari/537.36'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
return None
except RequestException:
return None
def parse_one_page(html):
pattern = re.compile(
'<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>'
'.*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>', re.S
)
items = re.findall(pattern, html)
for item in items:
yield {
'index': item[0],
'image': item[1],
'title': item[2],
'actor': item[3].strip()[3:],
'time': item[4].strip()[5:],
'score': item[5] + item[6]
}
def write_to_file(content):
with open('result_maoyan.txt', 'a', encoding='utf-8') as f:
f.write(json.dumps(content, ensure_ascii=False) + '\n')
def main(offset):
url = 'https://maoyan.com/board/4?offset=' + str(offset)
html = get_one_page(url)
for item in parse_one_page(html):
print (item)
write_to_file(item)
if __name__ == '__main__':
for i in range(10):
main(offset = i*10)
time.sleep(1)
详解
首先是抓取单页请求信息,一些内容直接码在代码里了
def get_one_page(url):
try:
# 伪装请求头改为Chrome, 配置头信息
# 猫眼有反爬,如果被识别为爬虫会给你返回个大嘴巴子,这里伪装Chrome浏览器
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chome/65.0.3325.162 Safari/537.36'
}
# 使用requests方法
response = requests.get(url, headers=headers)
# 通过状态码判断是否出现问题
if response.status_code == 200:
# 如果没有问题就返回抓取的页面信息
return response.text
return None
except RequestException: # 我想良好的代码风格应该少不了try-expect
return None
第二部分主要是通过正则表达式提取有价值信息,主要就是正则表达式的使用
有部分涉及到 yield 的使用,贴一篇前辈的文章,关于 yield 讲的比较清楚
def parse_one_page(html):
pattern = re.compile(
'<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>'
'.*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>', re.S
)
# re.compile()是把字符串转化成正则表达式常用的方法,之后使用findall方法
items = re.findall(pattern, html)
for item in items:
# yield 是我第一次用,就类似于特殊的return,返回设定的字典数据类型
yield {
'index': item[0],
'image': item[1],
'title': item[2],
'actor': item[3].strip()[3:],
'time': item[4].strip()[5:],
'score': item[5] + item[6]
}
关于正则表达式,我也是好久才明白,其实匹配的就是 (.*?) 里面的东西。我们看下面的正则表达式:
pattern = re.compile(
'<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>'
'.*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>', re.S
)
现来分析一下网页源码:
我们主要提取以下内容:
- 排名信息
- 电影图片
- 电影名称
- 主演
- 发布时间
- 评分
就以排名信息为栗子:
我们所要获取的,就是 1 这个数字,正则表达式如下:
<dd>.*?board-index.*?>(.*?)</i>
这一部分开始于 < dd > 结束于 < /i > 后面的那个 ( .*? ) 就是我们要匹配的内容。
然后我们写入文件
def write_to_file(content):
with open('result_maoyan.txt', 'a', encoding='utf-8') as f:
f.write(json.dumps(content, ensure_ascii=False) + '\n')
调用函数是这样的
def main(offset):
url = 'https://maoyan.com/board/4?offset=' + str(offset)
html = get_one_page(url)
for item in parse_one_page(html):
print (item)
write_to_file(item)
由于猫眼每页只显示10条信息,我们先看一下URL有什么规律:
第一页:
第二页:
第三页:
懂了吧,offset就是传入的那个最后的数据,之后调用请求获取当页信息的函数,写入文件的函数,就OK了。
主函数
if __name__ == '__main__':
for i in range(10):
main(offset = i*10)
time.sleep(1)
这里用了 time.sleep 方法,如果我们访问时间过快,会被判定为非正常访问就会被封 IP 不能再继续爬取,这里设定间隔 1 s。
总结
几个关键点:
-
请求头处理。
一般来讲,现在许多网站都有反爬措施,如果检测请求头,发现是来自爬虫,那么多半会拒绝你的访问,所以这里修改了请求头。
-
正则表达式。
这个还是要多练多去看别人是怎么写的。
-
请求时间。
不要过快就好,模仿人类速度。
要开始学Go了,后面的项目有涉及到区块链,有时间更一篇区块链的吧。还有非自然死亡真的太好看了8也!!!