http://www.mtime.com/top/movie/top100/
import os
import requests
from pyquery import PyQuery as pq
代码解析:
class Model():
def __repr__(self):
name = self.__class__.__name__
properties = ('{}=({})'.format(k, v) for k, v in self.__dict__.items())
s = '\n<{} \n {}>'.format(name, '\n '.join(properties))
return s
class Movie(Model):
def __init__(self):
self.name = ''
self.jury = ''
self.score = 0
self.quote = ''
self.cover_url = ''
self.ranking = 0
继承 Model
基类,这里主要通过属性存储数据,设定默认值;
def cached_page(url):
folder = 'cached'
if not os.path.exists(folder):
os.makedirs(folder)
# 为什么不能用find()
if '-' in url:
filename = '{}.html'.format(url.split('-', 1)[-1].split('.', 1)[0])
# print(filename)
else:
filename = '1.html'
# print(filename)
# 妈的
path = os.path.join(folder, filename)
# path.replace('\\', '/')
# print(path)
if os.path.exists(path):
with open(path, 'rb') as f:
s = f.read()
return s
else:
r = requests.get(url)
with open(path, 'wb') as f:
f.write(r.content)
return r.content
- os.path 返回当前路径;
- 判断路径下是否存在该文件夹,否则创建一个;
def movie_from_li(li):
e = pq(li)
m = Movie()
# 怎么找到父元素众多类子元素中的第一个
m.name = e('.mov_con').find('.px14').find('a').text()
m.jury = e('.mov_point').find('p').text()
# 怎么精简,主演怎么合并到一起
m.score = e('.mov_point').find('.total').text() + e('.mov_point').find('.total2').text()
# print(e('.mov_point').find('.total').text() + e('.mov_point').find('.total2').text())
m.quote = e('.mt3').text()
m.cover_url = e('img').attr('src')
m.ranking = e('.number').find('em').text()
return m
- 这里要继续将
li
元素实例化为pyquery
对象,才能进行css
选择操作。 -
m.name = e('.mov_con').find('.px14').find('a').text()
这个为什么不需要实例化就能使用.find()
方法了呢?上面的li
是遍历find()
拿到的数据;这是一个连缀。 - 元素的文本数据由
.text()
方法拿到,input
元素的文本数据由.value
属性拿到,属性由.attr(‘src’)
方法拿到; - 最后返回一个类的实例,储存着爬取的数据;
def movies_from_url(url):
page = cached_page(url)
# 支持 css 语法的对象
e = pq(page)
# find()方法可以返回一个列表(如果找的元素较多的话)
lis = e('#asyncRatingRegion').find('li')
# print(lis)
movies = [movie_from_li(i) for i in lis]
return movies
cached_page(url)
函数返回页面的 HTML
内容,pq(page)
将 HTML
内容转换为 PyQuery
实例,实现 css(jQuery)
的选择功能。
.find()
方法返回的是具备条件的所有后代(子、孙...),不能 [0]
(那么如何精确定位到第几个呢?);
def main():
for i in range(1, 11):
if i == 1:
url = 'http://www.mtime.com/top/movie/top100/'
else:
url = 'http://www.mtime.com/top/movie/top100/index-{}.html'.format(i)
movies = movies_from_url(url)
# url = 'http://www.mtime.com/top/movie/top100/'
# movies = movies_from_url(url)
print('top100 movies', movies)
if __name__ == '__main__':
main()
时光网100部电影用10个页面盛放,url
有一定的规律,通过遍历 url
爬取相应的页面。
第一个页面路径后面没有 .html
,所以需要单独交代;
小知识点:
- .find() 获得的是所有的后代(子、孙...)元素,.querySelector() 获得第一个元素,.querySelectorAll() 获得所有;
- python str.find(a, 1),字符串的find()方法返回的是子串在母串中的位置,没有返回-1,后面的参数1表示第一个子串a;
二、下载图片
三、伪装登录
四、动态内容爬取
网友评论