Requests+正则表达式爬取猫眼电影
目标
通过Request+正则表达式爬取猫眼电影TOP100电影的排名、名字、电影封面图片、主演、上映时间、猫眼评分,将爬取的内容写入文件中。
流程框架
进入到猫眼电影TOP100的页面,此时的URL为http://maoyan.com/board/4
,点击第2页,会发现此时的URL为http://maoyan.com/board/4?offset=10
,点击第3页,会发现URL变成了http://maoyan.com/board/4?offset=20
,由此可以推断出offset参数为偏移量,如果偏移量为n,则显示电影序号就是n+1到n+10,每页显示10个,所以,如果想获取TOP100电影,只需要分开请求10次,而10次的offset参数分别设置为0、10、20......90即可,这样获取不同的页面之后,再用正则表达式提取出相关信息,就可以得到TOP100的所有电影信息了。获取信息后,可以将信息写入txt文件,当然可以存入数据库(此处为了偷懒,就不存入数据库了)。为了加快爬取网页的速度,可以开启循环和多线程(当需要爬取的信息很大时,这是一个不错的技巧)。
下图展示了具体的流程框架:
(1)抓取单页内容
# 获取单个页面的HTML代码 def get_one_page(url): try: # 此处如果不加headers进行伪装,将会返回403错误(拒绝访问) headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36" } response = requests.get(url, headers = headers) # 如果返回的状态码是200,表示请求正常,返回页面HTML代码 # 否则,返回None if response.status_code == 200: return response.text return None except RequestException: return None
接下来测试一下是否可以获取页面内容:
if __name__ == '__main__': url = 'http://maoyan.com/board/4' html = get_one_page(url) print(html)
(2)正则表达式分析
可以对get_one_page(url)函数爬取的HTML代码进行分析(此处为了方便观看,直接在浏览器控制台分析),利用正则表达式获取到有用的信息(电影的排名、名字、电影封面图片、主演、上映时间、猫眼评分)。
# 解析单个页面的HTML代码,利用re模块提取出有效信息 def parse_one_page(html): # re.S:表示“.”的作用扩展到整个字符串,包括“\n” pattern = re.compile('<dd>.*?board-index.*?>(\d+)</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] }
接下来测试一下是否可以得到我们想要的内容:
if __name__ == '__main__': url = 'http://maoyan.com/board/4' html = get_one_page(url) items = parse_one_page(html) for item in items: print(item)
控制台输出如下:
单个页面信息解析正确,那么,想要获得多个页面的信息,只需写一个循环遍历即可:
def main(offset): url = 'http://maoyan.com/board/4?offset=' + str(offset) html = get_one_page(url) for item in parse_one_page(html): print(item) if __name__ == '__main__': for i in range(10): main(i*10)
(3)保存至文件
只需写一个简单的函数即可完成,但此处需要注意一点,为保证输出文件为中文,在读写文件时要添加参数endcoding="utf-8"
。
# 将解析出的内容写入文件 def write_to_file(content): # 添加endcoding="utf-8"确保输出到文件中为中文 with open('result.txt', 'a', encoding='utf-8 ') as f: # 此处建议将解析出的内容编码为json格式再写入文件,json的好处在此不过多叙述 # 如果使用了json进行编码,务必添加参数ensure_ascii=False确保编码数据为中文 # json.dumps():编码json数据 f.write(json.dumps(content, ensure_ascii=False) + '\n') f.close()
运行代码,目标信息被写入result.txt文件中:
(4)开启循环及多线程
为了加快页面爬取速度,可以使用多线程(针对大量数据时非常有效)。
if __name__ == '__main__': pool = Pool() pool.map(main, [i*10 for i in range(10)])
项目完整代码已托管到github:https://github.com/panjings/p...