抓取页面: https://maoyan.com/board/4 (猫眼电影 TOP100)
每页有10个电影、总共10页。每页后面会增加一个 ?offset=数字
第一页地址为: https://maoyan.com/board/4
第二页地址为: https://maoyan.com/board/4?offset=10
第十页地址为:https://maoyan.com/board/4?offset=90
需要用到的库
import requests #发起请求
from requests.exceptions import RequestException #错误处理
import re #正则匹配
import json #导出内容要用
from multiprocessing import Pool #多进程,可选
整体结构
def get_one_page(url): #抓取一个页面
def parse_one_page(html): #获取一个页面内内容(电影信息)
def write_to_file(content): #写入一个文件
def main(offset): #把上面三个定义串起来
if __name__ == '__main__': #执行main
获取单个页面
def get_one_page(url):
try:
headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36'}
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
return None
except RequestException:
return None
- 首先定义一个函数 ``` def get_one_page(url):
2. 错误判断
def get_one_page(url): try: … except RequestException: return None
3. 传入headers
> 模拟浏览器,告诉浏览器不是爬虫,这部分可以通过浏览器查看源代码,然后拷贝,注意:拷贝出来的写法不是字典的格式,要改下
headers = {‘User-Agent’:’Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36’}
4. 加入if 判断状态码,如果是200就正常返回,不是200 就返回 `None`
response = requests.get(url, headers=headers) if response.status_code == 200: return response.text return None
## 获取单页内的内容
def parse_one_page(html): pattern = re.compile(‘
1. 定义一个函数
def parse_one_page(html):
2. 正则获取单个电影信息
pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
> 其中: `re.S` 表示匹配所有字符,包括换行符。<br />
每个电影信息都保存在一个里,我们从里面获取了 **排名、名称、图片、导演、时间**等信息
3. 我们把这个正则的规则传入了 `pattern` 方便复用
3. items 找到这个页面里面所有的电影信息
3. item 做一个循环,item 里面的 yield 把单个电影信息给标注出来,并且用字典的形式
### 以下两种写法效果一样
#### 正则连写
pattern = re.compile(‘
#### 分行写
每行用 `'`...`'` 包括,另外第二行起要在 `'`...`'` 前面加一个 `+`
pattern = re.compile(‘
## 写入文件
def write_to_file(content): with open(‘rusult.txt’, ‘a’, encoding=’utf-8’) as f: f.write(json.dumps(content, ensure_ascii=False) + ‘\n’) f.close()
1. 输出汉字 `encoding='utf-8'`,`ensure_ascii=False` 如果不是会二进制的方式传入
1. 要关闭 `f.close()`
## def main(offset) 串起来
1. `url = 'https://maoyan.com/board/4?offset=' + str(offset)` 其中 `str(offset)` 是一个可有可无的。
1. 然后依次串起来,把 URL 给 `html = get_one_page(url)`
1. 把上面的html 传入这个 函数 `for item in parse_one_page(html):`
1. 打印 item 也就是单条 电影信息
1. 写入 item 到文件 `write_to_file(item)`
## `if __name__ == '__main__':`
if name == ‘main‘: for i in range(10): main(i*10)
## 完整代码
import requests from requests.exceptions import RequestException import re import json
def get_one_page(url): try: headers = {‘User-Agent’:’Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 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(‘
def write_to_file(content): with open(‘rusult.txt’, ‘a’, encoding=’utf-8’) as f: # 为了输出汉字 encoding=’utf-8’ f.write(json.dumps(content, ensure_ascii=False) + ‘\n’) #为了输出汉字 ensure_ascii=False f.close()
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(i*10)
## 多进程抓取
可以实现秒抓
-
引入库 `from multiprocessing import Pool`
-
修改最后 `if __name__ == '__main__':`里的内容为如下
if name == ‘main‘: pool = pool() pool.map(main, [i*10 for i in range(10)])
import requests from requests.exceptions import RequestException import re import json from multiprocessing import Pool
def get_one_page(url): try: headers = {‘User-Agent’:’Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 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(‘
def write_to_file(content): with open(‘rusult.txt’, ‘a’, encoding=’utf-8’) as f: # 为了输出汉字 encoding=’utf-8’ f.write(json.dumps(content, ensure_ascii=False) + ‘\n’) #为了输出汉字 ensure_ascii=False f.close()
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‘: pool = Pool() # 后面的一个Pool 的 P 是大写。 pool.map(main, [i*10 for i in range(10)])
```