周天我也没课的,您给安排一下吧!:)——致某某某
最近系统的开始了爬虫的学习,虽然以前也写过不少,但是现在跟着书学,感觉学会了不少,这里来分享一下。
我们今天的目标是猫眼电影top100
将要用到的库:
import re
import requests
import time
import json
from requests.exceptions import RequestException
网址——https://maoyan.com/board/4,用浏览器打开:
image.png
这是猫眼首页,我们需要的信息在这里都可以看到——电影排名、电影图片、电影名、主演、上映时间、评分。
这次我没用BeautifulSoup库来解析html,用的是正则表达式,刚好学过,就赶紧试用了下。打开网页后按F12,打开开发者工具,在调试一栏中打开源码。不要在查看器、element里查看,因为这里面的可能是JavaScript渲染过后的文件,并不是我们得到的响应源码。
dd
经过观察,我们要的信息在
1
9.5
然后将我们要的信息改成: (.?),找到标志位,将其余字符全部用:.? 替代。
如下:
.*?board-index.*?>(.*?).*?data-src="('+
'.*?)".*?"name">(.*?).*?star">('+
'.*?).*?releasetime">(.*?).*?integer">('+
'.*?).*?fraction">(.*?).*?
所以就有了我们的解析页面的函数:
def parser_one_page(html):
'''
解析一页的10部电影信息
输入html对象
输出需要的信息->dict
.*?board-index.*?>(.*?).*?data-src="(.*?)".*?
name.*?a.*?>(.*?).*?"star">(.*?).*?releasetime"
>(.*?).*?integer">(.*?).*?fraction">(.*?)
'''
pattern = re.compile('.*?board-index.*?>(.*?).*?data-src="('+
'.*?)".*?"name">(.*?).*?star">('+
'.*?).*?releasetime">(.*?).*?integer">('+
'.*?).*?fraction">(.*?).*? ', re.S)
items = re.findall(pattern, html)
for i in items:
yield {
'index': i[0],
'image': i[1],
'name': i[2],
'actor': i[3].strip()[3:],
'releasetime': i[4].strip()[5:],
'score': i[5]+i[6],
}
前面要获取首页源码:
def get_one_page(url):
'''
获取猫眼top100的一页源码
输入网页url
输出源码'''
try:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0)'
' Gecko/20100101 Firefox/66.0'}
response = requests.get(url, headers=headers)
if response.status_code == 200:
print(200)
return response.text
return None
except RequestException:
return None
然后是将其保存到文件:
def write_to_file(content):
'''将处理完成的文件放到
输入处理好的内容
将内容存储到文件'''
with open('result.txt', 'a', encoding='utf-8') as f:
f.write(json.dumps(content, ensure_ascii=False) + '\n')
main函数:
def main(offset):
'''输入每一页的偏移量'''
url = "https://maoyan.com/board/4?offset="+str(offset)
html = get_one_page(url)
contents = parser_one_page(html)
for item in contents:
print(item)
write_to_file(item)
我发现换页后url多了一个偏移量offset,每页10部电影,即第一页从0开始,第二页从10开始,一次类推,得出:0,10,20,......,90,一共10页,我们写个循环:
if __name__ == "__main__":
for i in range(10):
main(i*10)
time.sleep(1)
因为猫眼有反爬机制,访问速度过快,会被禁止访问,所以我们用了1s的延时。
运行后的成果:
输出
result.txt
这次我们用的是requests库,这比urllib好用很多,用了正则表达式代替beautifulsoup,用了json数据格式来存储数据,非常简单,正则表达式很强大!几乎万能,就是当式子较长后比较闹心。
就这样!
全部代码:
import re
import requests
import time
import json
from requests.exceptions import RequestException
def get_one_page(url):
'''
获取猫眼top100的一页源码
输入网页url
输出源码'''
try:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0)'
' Gecko/20100101 Firefox/66.0'}
response = requests.get(url, headers=headers)
if response.status_code == 200:
print(200)
return response.text
return None
except RequestException:
return None
def parser_one_page(html):
'''
解析一页的10部电影信息
输入html对象
输出需要的信息->dict
.*?board-index.*?>(.*?).*?data-src="(.*?)".*?name.*?a.*?>(.*?).*?"star">(.*?).*?releasetime">(.*?).*?integer">(.*?).*?fraction">(.*?)
'''
# regex='.*?board-index.*?>(.*?).*?data-src="(.*?)".*?name.*?a.*?>(' \
# '.*?).*?"star">(.*?).*?"releasetime">(.*?).*?"integer">(' \
# '.*?).*?"fraction">(.*?)'
pattern = re.compile('.*?board-index.*?>(.*?).*?data-src="('+
'.*?)".*?"name">(.*?).*?star">('+
'.*?).*?releasetime">(.*?).*?integer">('+
'.*?).*?fraction">(.*?).*? ', re.S)
items = re.findall(pattern, html)
for i in items:
yield {
'index': i[0],
'image': i[1],
'name': i[2],
'actor': i[3].strip()[3:],
'releasetime': i[4].strip()[5:],
'score': i[5]+i[6],
}
def write_to_file(content):
'''将处理完成的文件放到
输入处理好的内容
将内容存储到文件'''
with open('result.txt', 'a', encoding='utf-8') as f:
f.write(json.dumps(content, ensure_ascii=False) + '\n')
def main(offset):
'''输入每一页的偏移量'''
url = "https://maoyan.com/board/4?offset="+str(offset)
html = get_one_page(url)
contents = parser_one_page(html)
for item in contents:
print(item)
write_to_file(item)
if __name__ == "__main__":
for i in range(10):
main(i*10)
time.sleep(1)
闲话我不放pyq了。只放,免得受您一顿批。