赞
踩
# 事先声明,运行环境:win10,pycharm+python3.5,Any question will be valued!
# 代码是根据这个修改的原来是python2,http://www.maiziedu.com/wiki/crawler/example/,为了进行一步理解python爬虫的原理,这个基础只之上进一步做出了修改,下面的url可以换成任意的网页,但是编码可能出现问题,
-
- import urllib
- import urllib.request
- #from html.parser import HTMLParser
- from html.parser import HTMLParser
- #print(dir(HTMLParser))
- import re
- import requests
-
- import time
- #print(dir(urllib.request.urlopen.__dict__))
-
- class MovieParser(HTMLParser): #定义电影解析器
-
- def __init__(self):
- HTMLParser.__init__(self) #调用父类的构造函数
- self.movies = [] #定义一个数组来保存电影,默认为空
-
- def handle_starttag(self,tag,attrs): #重载这个方法,去解析li这个数据
- # tag 是标签 attrs是属性列表[(属性,对应属性的值),...],元组的列表
-
- #print("Done!'\n")
- #print(tag,attrs)
- print(" tag : {0} | attrs : {1}\n".format(tag,attrs))
- def _attr(attrlist,attrname):#定义一个函数来解析属性
- #time.sleep(10)
- for attr in attrlist:
- #print(attr,attr[0],attrname)
- if attr[0] == attrname: #如果这个属性名称和要求的一样
- #print(attr[1])
- return attr[1] #返回属性的值
- return None #如果没有找到返回空
- if len(attrs)>0:
- #print(" tag : {0} |attrs : {1}\n".format(tag, attrs))
- if tag == 'li' and _attr(attrs,'data-title') is not None:
- #print(attrs)
- movie = {}
- movie['title'] = _attr(attrs,'data-title') #电影名称
- movie['score'] = _attr(attrs,'data-score') #电影分数
- movie['director'] = _attr(attrs,'data-director') #电影导演
- movie['actors'] = _attr(attrs,'data-actors') # 电影演员
- self.movies.append(movie) #提取出的电影放到列表里面
- #print('%(title)s|%(score)s|%(director)s|%(actors)s' % movie)
- print('%(title)s|%(score)s|%(director)s|%(actors)s' % movie)
-
-
-
-
-
- def nowplaying_movies(url):
- #headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.73 Safari/537.36'} #
- headers = {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36'}
- #请求头
- #模拟一个浏览器的行为
- #req = urllib.request(url, headers=headers) #定制一个http头
- print(url)
- #s = urllib.request.urlopen(url) #获取这个请求
- s = requests.get(url,headers=headers)
- s.encoding = 'utf-8' #防止发生编码错误
- #print(s.read()) # 读取得是字节类型,必须进行解码
- parser = MovieParser() #解析器
- #print(s.content.decode('utf-8')) #解码之后得到整个h网页得代码,里面有我们需要得内容
- # 使用utf-8进行解码
- parser.feed(s.content.decode())
-
- #s.close()
- return parser.movies #把解析器里面的movies返回给调用者
-
- if __name__ == '__main__':
-
- #url = 'http://movie.douban.com/nowplaying/xiamen/' #豆瓣热播电影的地址,还有分城市
- url = 'http://www.maiziedu.com/wiki/crawler/multi/'
- movies = nowplaying_movies(url) #定义一个函数nowplaying_movies,就是当前正在热播的电影,我们希望这个函数传进去就是url,还会就是一个电影列表
-
- import json
-
- #json 默认使用ASCII编码,所以不显示汉字
- print('%s' % json.dumps(movies, ensure_ascii=False,sort_keys=True, indent=4, separators=(',', ': '))) # 这个电影列表通过 json把它编码一下,打印出来
-
- <!DOCTYPE html>
- <html lang="zh-cmn-Hans" class="ua-windows ua-webkit">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <meta name="renderer" content="webkit">
- <meta name="referrer" content="always">
- <meta name="google-site-verification" content="ok0wCgT20tBBgo9_zat2iAcimtN4Ftf5ccsh092Xeyw" />
- <title>
- 厦门 - 在线购票&影讯
- </title>
-
- <meta name="baidu-site-verification" content="cZdR4xxR7RxmM4zE" />
- <meta http-equiv="Pragma" content="no-cache">
- <meta http-equiv="Expires" content="Sun, 6 Mar 2005 01:00:00 GMT">
-
-
- <meta name="keywords" content="厦门,在线购票,网上电影票预订,优惠电影票,影讯,排片,放映时间,电影票价"/>
- <meta name="description" content="厦门电影院在线优惠购票及影讯排片查询"/>
-
- <link rel="apple-touch-icon" href="/pics/movie/apple-touch-icon.png">
- <link href="https://img3.doubanio.com/f/shire/52c9997d6d42db58eab418e976a14d5f3eff981e/css/douban.css" rel="stylesheet" type="text/css">
- <link href="https://img3.doubanio.com/f/shire/ae3f5a3e3085968370b1fc63afcecb22d3284848/css/separation/_all.css" rel="stylesheet" type="text/css">
- <link href="https://img3.doubanio.com/f/epstein/85f16e2319c370ecd16bbca53d5d006adaa99728/css/movie/base/init.css" rel="stylesheet" type="text/css">
- <script type="text/javascript">var _head_start = new Date();</script>
- <script type="text/javascript" src="https://img3.doubanio.com/f/epstein/0495cb173e298c28593766009c7b0a953246c5b5/js/movie/lib/jquery.js"></script>
- <script type="text/javascript" src="https://img3.doubanio.com/f/shire/1316664523258f7b8b536e4ce45afc9cb37b8963/js/douban.js"></script>
- <script type="text/javascript" src="https://img3.doubanio.com/f/shire/0efdc63b77f895eaf85281fb0e44d435c6239a3f/js/separation/_all.js"></script>
上面是打印出的原始网页(由于网页太长),可在任意浏览器中打开检查元素就可以进行对比是不是原始网页,我们所有需要的东西都在上面的网页里面,其实上面的html代码关键就是标签tag,和标签对应的属性名attrname,以及属性的值attrvalue,这3个东西,这也是我们爬虫的关键的3个部分,我们爬虫其实就是根据tag,attrname,attrvalue进行逐层的查找匹配(正则表达式),首先我们要在网页源码中找到我们需要的东西(一般都是attrvalue),然后看这个attrname在哪个attrname下面包含着,最后找到包含这个attrname的tag。
那么我们如何得到网页的tag,和attrname,attrvalue呢,我们可以通过重写HTMLParser的handle_starttag方法,通过这个方法可以得到每个tag(str),和其对应的tuple= (attrname,attrvalue)的列表(list),这样就可以通过遍历进行匹配了。下面我们打印出来就一目了然了。
- tag : li | attrs : [('id', '26794435'), ('class', 'list-item hidden'), ('data-title', '哪吒之魔童降世'), ('data-score', '8.6'), ('data-star', '45'), ('data-release', '2019'), ('data-duration', '110分钟'), ('data-region', '中国大陆'), ('data-director', '饺子'), ('data-actors', '吕艳婷 / 囧森瑟夫 / 瀚墨'), ('data-category', 'nowplaying'), ('data-enough', 'True'), ('data-showed', 'True'), ('data-votecount', '943503'), ('data-subject', '26794435')]
-
- 哪吒之魔童降世|8.6|饺子|吕艳婷 / 囧森瑟夫 / 瀚墨
- tag : ul | attrs : [('class', '')]
-
- tag : li | attrs : [('class', 'poster')]
-
- tag : a | attrs : [('href', 'https://movie.douban.com/subject/26794435/?from=playing_poster'), ('class', 'ticket-btn'), ('target', '_blank'), ('data-psource', 'poster')]
-
- tag : img | attrs : [('src', 'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2563780504.jpg'), ('alt', '哪吒之魔童降世'), ('rel', 'nofollow'), ('class', '')]
-
- tag : li | attrs : [('class', 'stitle')]
-
- tag : a | attrs : [('href', 'https://movie.douban.com/subject/26794435/?from=playing_poster'), ('class', 'ticket-btn'), ('target', '_blank'), ('title', '哪吒之魔童降世'), ('data-psource', 'title')]
- [
- {
- "actors": "唐国强 / 刘劲 / 黄景瑜",
- "director": "黄建新 宁海强",
- "score": "7.0",
- "title": "决胜时刻"
- },
- {
- "actors": "黄渤 / 张译 / 吴京",
- "director": "陈凯歌 张一白 管虎 薛晓路 徐峥 宁浩 文牧野",
- "score": "0",
- "title": "我和我的祖国"
- },
- {
- "actors": "平采娜·乐维瑟派布恩 / 奈哈·西贡索邦 / 杰森·杨",
- "director": "查亚诺普·布恩帕拉科布",
- "score": "6.6",
- "title": "友情以上"
- },
- {
- "actors": "山新 / 郝祥海 / 刘明月",
- "director": "木头",
- "score": "8.2",
- "title": "罗小黑战记"
- },
- {
- "actors": "吴京 / 章子怡 / 张译",
- "director": "李仁港",
- "score": "0",
- "title": "攀登者"
- },
- {
- "actors": "肖战 / 李沁 / 孟美岐",
- "director": "程小东",
- "score": "5.3",
- "title": "诛仙 Ⅰ"
- },
- {
- "actors": "任达华 / 梁咏琪 / 罗仲谦",
- "director": "罗永昌",
- "score": "6.9",
- "title": "小Q"
- },
以知乎问答为例,对于其他的网页比如今日头条和淘宝美团点评也类似,
打开https://www.zhihu.com/question/21400402,打开浏览器检查->网络->XHR
首先找到这个问题下第一个回答对应的url连接,见上图第一个空色方框,由于一个网页可以容纳的回答有限,这里总共有225个回答,鼠标往下滚动刷新,发现最左边的内容变多了,我们通过第一个url只能获取5个回答,那么如何获取所有的回答呢,如果我们能发现所有url的规律不是可以了?
通过分析表头的url参数可知不同的回答有个offset参数不一样其他都是一样的,直接循环一下就好了,当然由于不同的前段方法有些参数也可以是page或者其他
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。