学习不断,进步不止。
本次,我跟着视频学习的是使用requests抓取猫眼top100榜单内容,并写入到文件。
首先,这是一个简单的抓取内容,抓取的是静态网页,不涉及js的渲染,难度较低。
跟着学,有以下几点精益和收获。也有几点需要指出的。模块化思维
抓一条,写一条,循环。(之前一直是,抓完,再一次性写入。这样对内存的占用会比较大)
正则表达式
yield用法
requests的异常处理。(之前最多判断一下状态码是不是200,这次加入了异常处理)
视频中教学的内容也需要经过检验,要有判别意识,不可完全照搬。
可能网上都是学习抓取猫眼,对猫眼榜单页面的pv\uv等指标产生干扰,猫眼在页面上加了简单的爬虫判别,用于隔离一部分爬虫初学的来试水。(如果你的requests不传入user-agent,网站会认为你是恶意访问而拒绝)【这一点在视频中没有提及】
with open as 本身就有close功能,无需再进行close,不知道为什么在视频中会再加上一个close操作。【疑惑】
废话不多说,直接上代码。
包的引入
head = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'}
import requests
import re
import json
from requests.exceptions import RequestException
获得页面代码,并返回成一个字符串
常规操作,不解释。
def get_one_page(url):
try:
res = requests.get(url,headers=head)
if res.status_code == 200:
return res.text
else:
print(res.status_code)
return None
except RequestException:
return None
正则表达式解析
这里的学习点,有正则表达式的写法。
我之前用正则都是再notepad++里面,爬虫当中我用的比较多的是BeautifulSoup或者pyquery(这两个都是html代码元素的解析)。
正则表达式,要注意一定要有结束符。
python使用正则的过程,先将字符串正则表达式转化成正则对象,后面加参数:re.S,适合使用在文档中包含换行符等字符的情况。之后用re.findall(正则对象,字符串)获得一个结果列表。
yield 的使用,yield可以构造迭代器
其中,还用到了数组切片的内容(a[5:]表示从数组第5个字符到最后),字符串处理的内容(strip),这些如有不清楚的,请百度一下。
def parse_one_page(html):
pattern =re.compile('
.*?board-index.*?>(\d+).*?data-src="(.*?)".*?"name".*?>(.*?).*?"star">(.*?).*?releasetime">(.*?).*?"integer">(.*?).*?"fraction">(.*?).*?',re.S)items = re.findall(pattern,html)
for i in items:
yield{
'index':i[0],
'imgUrl':i[1],
'name':i[2],
'actor':i[3].strip()[3:],
'time':i[4][5:],
'score':i[5]+i[6]
}
写入到文件
这里用到了json转字符串的内容,即json.dumps(content),正常转换,会将原本的文字转成ASCII码,如想变为正常汉字,需要加一个参数:ensure_ascii=False,同时在文件创建或者打开的时候,采用utf-8格式。
def tofile(content):
#json格式字符串会将汉字变成ASCII,需要调整参数,转换成汉字
with open('test.txt','a',encoding='utf-8') as f:
f.write(json.dumps(content,ensure_ascii=False)+'\n')
循环
这里值得学习的是,采用抓取一条,写一条,再循环的流程。内存压力较小。
def main(offset):
url = 'http://maoyan.com/board/4?offset='+str(offset)
html = get_one_page(url)
for i in parse_one_page(html):
print(i)
tofile(i)
翻页
if __name__=='__main__':
for i in range(10):
main(i*10)