抓取页面: 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

需要用到的库

  1. import requests #发起请求
  2. from requests.exceptions import RequestException #错误处理
  3. import re #正则匹配
  4. import json #导出内容要用
  5. from multiprocessing import Pool #多进程,可选

整体结构

  1. def get_one_page(url): #抓取一个页面
  2. def parse_one_page(html): #获取一个页面内内容(电影信息)
  3. def write_to_file(content): #写入一个文件
  4. def main(offset): #把上面三个定义串起来
  5. if __name__ == '__main__': #执行main

获取单个页面

  1. def get_one_page(url):
  2. try:
  3. 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. response = requests.get(url, headers=headers)
  5. if response.status_code == 200:
  6. return response.text
  7. return None
  8. except RequestException:
  9. return None
  1. 首先定义一个函数 ``` def get_one_page(url):
  1. 2. 错误判断

def get_one_page(url): try: … except RequestException: return None

  1. 3. 传入headers
  2. > 模拟浏览器,告诉浏览器不是爬虫,这部分可以通过浏览器查看源代码,然后拷贝,注意:拷贝出来的写法不是字典的格式,要改下

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’}

  1. 4. 加入if 判断状态码,如果是200就正常返回,不是200 就返回 `None`

response = requests.get(url, headers=headers) if response.status_code == 200: return response.text return None

  1. ## 获取单页内的内容

def parse_one_page(html): pattern = re.compile(‘

.?board-index.?>(\d+).?data-src=”(.?)”.?name”><a.?>(.?).?star”>(.?)

.
?releasetime”>(.?)

.
?integer”>(.?).?fraction”>(.?).?
‘, 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:], #.strip() 去掉换行符 ‘time’: item[4].strip()[5:], #[5:]去掉前面的5个字符,包括冒号 ‘score’: item[5]+item[6] }

  1. 1. 定义一个函数

def parse_one_page(html):

  1. 2. 正则获取单个电影信息
  1. pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
  1. > 其中: `re.S` 表示匹配所有字符,包括换行符。<br />
  2. 每个电影信息都保存在一个里,我们从里面获取了 **排名、名称、图片、导演、时间**等信息
  3. 3. 我们把这个正则的规则传入了 `pattern` 方便复用
  4. 3. items 找到这个页面里面所有的电影信息
  5. 3. item 做一个循环,item 里面的 yield 把单个电影信息给标注出来,并且用字典的形式
  6. ### 以下两种写法效果一样
  7. #### 正则连写

pattern = re.compile(‘

.?board-index.?>(\d+).?data-src=”(.?)”.?name”><a.?>(.?).?star”>(.?)

.
?releasetime”>(.?)

.
?integer”>(.?).?fraction”>(.?).?
‘, re.S)

  1. #### 分行写
  2. 每行用 `'`...`'` 包括,另外第二行起要在 `'`...`'` 前面加一个 `+`

pattern = re.compile(‘

.?board-index.?>(\d+).?data-src=”(.?)”.?name”><a’ +’.?>(.?).?star”>(.?)

.
?releasetime”>(.?)

‘ +’.
?integer”>(.?).?fraction”>(.?).?
‘, re.S)

  1. ## 写入文件

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. 1. 输出汉字 `encoding='utf-8'`,`ensure_ascii=False` 如果不是会二进制的方式传入
  2. 1. 要关闭 `f.close()`
  3. ## def main(offset) 串起来
  4. 1. `url = 'https://maoyan.com/board/4?offset=' + str(offset)` 其中 `str(offset)` 是一个可有可无的。
  5. 1. 然后依次串起来,把 URL `html = get_one_page(url)`
  6. 1. 把上面的html 传入这个 函数 `for item in parse_one_page(html):`
  7. 1. 打印 item 也就是单条 电影信息
  8. 1. 写入 item 到文件 `write_to_file(item)`
  9. ## `if __name__ == '__main__':`

if name == ‘main‘: for i in range(10): main(i*10)

  1. ## 完整代码

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(‘

.?board-index.?>(\d+).?data-src=”(.?)”.?name”><a.?>(.?).?star”>(.?)

.
?releasetime”>(.?)

.
?integer”>(.?).?fraction”>(.?).?
‘, 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:], #.strip() 去掉换行符 ‘time’: item[4].strip()[5:], #[5:]去掉前面的5个字符,包括冒号 ‘score’: item[5]+item[6] }

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)

  1. ## 多进程抓取
  2. 可以实现秒抓
  3. -
  4. 引入库 `from multiprocessing import Pool`
  5. -
  6. 修改最后 `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(‘

.?board-index.?>(\d+).?data-src=”(.?)”.?name”><a.?>(.?).?star”>(.?)

.
?releasetime”>(.?)

.
?integer”>(.?).?fraction”>(.?).?
‘, 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:], #.strip() 去掉换行符 ‘time’: item[4].strip()[5:], #[5:]去掉前面的5个字符,包括冒号 ‘score’: item[5]+item[6] }

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)])

```