“受尽苦难而不厌,此乃修罗之路”
本文技术含量过低,请谨慎观看
之前用R语言的Rcurl包做过爬虫,给自己的第一感觉是比较费劲,看着看着发际线就愈加亮眼,最后果断丢之。不过好的是和python爬取原理基本一致,且听说python拥有大量网页解析库,结合MongoDB等存储数据库,爬虫效率大大调高,所以按捺不住心中之寂寞,故爬之。
在学习了几天基础知识后,今天就做了第一次python爬虫尝试,目标是大多数菜鸟入门必爬的猫眼电影Top榜单数据。可能大家爬得多了,猫眼的反爬机制在大伙的锤炼下渐渐成熟,我知道的一些方法比如使用代理、伪造headers或者是用selenium驱动浏览器都进不去。查了一些资料,目前只发现了使用登录网站后的cookies才能进去,只是这样猫眼会知道是你小子在爬它。
好的,下面进入正题:
1. 网页分析
Top100榜单,每一页显示10个,不同网页的规律是网址末尾offset = 0,10,20,30……90。查看源码发现每部电影都是在一个dd标签里。
介绍一个在线转cookies为python格式的工具:https://curl.trillworks.com/2. 请求单页内容
import requestsfrom requests.exceptions import RequestException #异常处理import re #正则表达式import json #将字典转为字符串from multiprocessing import Pool #从multiprocessing引入进程池def get_one_page(url):try: headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'} cookies = {……}#此处复制自己的cookies response = requests.get(url,headers=headers,cookies=cookies)if response.status_code == 200: #状态码为200表示请求成功return response.text #获取源码return Noneexcept RequestException: #这里我们只定义了父类异常,你也可以再详细一点return None
3. 解析html
本例用正则表达式的方法:def parse_one_page(html): #解析html代码 pattern = re.compile('.*?board-index.*?>(\d+).*?src="(.*?)".*?name">+'.*?>(.*?)(.*?)(.*?).*?integer">(.*?)'+'.*?fraction">(.*?).*?',re.S) items = re.findall(pattern,html)#print(items) #此时以列表形式存储,每个元素是一个元组for item in items: #变为好看的字典形式yield{ #变成一个生成器,并且理解为一个return'index': item[0],'image': item[1],'title': item[2],'actor': item[3].strip()[3:],#去掉换行符,且不要“主演:”'time': item[4].strip()[5:], #去掉换行符,且从第5个位置输出'score': item[5]+item[6] #评分是将两个部分拼接 }
4. 写入文件def write_to_file(content): #content是一个字典的形式with open("result.txt",'a',encoding= 'utf-8') as f: #'a'表示往后追加 f.write(json.dumps(content, ensure_ascii=False)+'\n') #json.dumps将其转为字符串的形式,字典的中括号也会成为字符串 f.close()
5. 主函数def main(offset): url = "http://maoyan.com/board/4?offset="+str(offset) html = get_one_page(url) #获取源码#print(html) #打印源码for item in parse_one_page(html):#print(item) #输出10个字典 write_to_file(item) #写入文件
6. 开启循环及多线程if __name__ == "__main__": #这个__main__和上面定义的main函数没有关系 #for i in range(10): # main(i*10) #map(main,[i*10 for i in range(10)]) #不理解为什么这句没有得到结果 pool = Pool() pool.map(main, [i*10 for i in range(10)])
7. 总结Top100电影数据