300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 爬取TOP100榜猫眼电影信息 爬虫实战

爬取TOP100榜猫眼电影信息 爬虫实战

时间:2020-07-06 04:57:38

相关推荐

爬取TOP100榜猫眼电影信息 爬虫实战

写在前面

最近在学爬虫,跟着崔庆才大佬的个人网站学习。

今天跟着做了一个爬虫来爬取猫眼电影top100榜的电影信息。其中遇到了一些问题,这里就写成博客记录下来。

遇到的问题

反爬虫机制:在进行html文档获取时,收到了403的状态码,这大概率代表是由于猫眼网站的反爬虫机制。这里的解决办法是在headers中加上user-agent信息。美团验证:在修改了headers之后,发现遇上了新的问题。收到的页面保存本地之后打开,发现是一个美团验证页面。通过这个页面,便可以正常访问,但我目前实力还做不到,所以寻找其他办法。最后发现,我之前修改头信息,user-agent中用的是火狐浏览器,而我之后尝试把修改成chrome之后便不会出现验证页面。源码在不同浏览器上显示不同:在写正则表达式时,在获取图片链接那一步总是发现不对,返回的结果是只有5个url,且url不对。然后我看了崔大佬写的正则表达式,他用的是data-src,但是我在源码上找了半天,却看不到这个data-src,最后终于发现,是浏览器的问题。我一开始用的是edge来查看源码,其中是没有data-src的,只有src,在换了火狐和chrome之后,便发现,原来真的是data-src。我也不知道为什么同样一样个网页在不同的浏览器上源码不一样,支持的html版本不一样?还是什么,无所谓了,我不是很关心原因是什么,但是这个坑我先mark了。

Firefox

edge

发现了这个问题之后,我才明白,怪不得本来应该匹配十个,最后只匹配到5个,且图片是错的原因:因为每个dd里,第二个img其实是data-src,而我写的src,所以它虽然是非贪婪,但只能匹配到下一个dd的第一个img,所以才会出现1,3,5,7,9这样的问题。

代码

这里我简单的做了注释(注释并不规范)

一个小经验,正则表达式还是写一段测试一段,不然全写完错了,猛的一看有点懵。

# 爬取猫眼电影Top100的电影名称、时间、评分、图片信息,提取的站点的url为/board/4结果以文件形式保存下来# 这里需要美团验证import requestsimport requests.cookiesimport reimport jsonimport timedef get_one_page(url):# 利用headers避免403反爬虫headers = {'Content-Type': 'text/plain; charset=UTF-8','Referer': '/board/4','Origin': '',# 不能用Firefox,出现的验证页面暂时无法解决'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36'}response = requests.get(url, headers=headers)# 指定response的编码response.encoding = response.apparent_encodingif response.status_code == 200:return response.textreturn Nonedef parse_one_page(html):# 不应该全部写好再提取,应该一个一个提取# 这里我是醉了,edge的源码显示与其他浏览器的源码显示不一样# 还是别以符号作为标志位,容易乱,还是以字母作为标志位pattern = pile('<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>.*?score">.*?>(.*?)</i>.*?">(.*?)</i>',re.S)items = re.findall(pattern, html)for item in items:#yield就是个return,但是是一次次的返回 关系到生成器 迭代器yield {'index': item[0],'image': item[1],'title': item[2].strip(),# 如果元组的长度大于3才执行前面的语句,否则返回空.[3:]表示从第三个字符开始'actor': item[3].strip()[3:] if len(item[3]) > 3 else '','time': item[4].strip()[5:] if len(item[4]) > 5 else '','score': item[5].strip() + item[6].strip()}def write_to_json(content):with open('result.txt', 'a', encoding='utf-8') as f:f.write(json.dumps(content, ensure_ascii=False) + '\n')def main(offset):url = '/board/4?offset='+str(offset)html = get_one_page(url)for item in parse_one_page(html):print(item)write_to_json(item)if __name__ == '__main__':for i in range(10):main(i*10)#睡眠,防止ip被封time.sleep(2)

结果

最后附上崔大佬的链接

/5534.html

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。