当前位置:   article > 正文

python爬虫的原理_python爬虫 实现原理

python爬虫 实现原理

先上代码再解释:

# 事先声明,运行环境:win10,pycharm+python3.5,Any question will be valued!

# 代码是根据这个修改的原来是python2,http://www.maiziedu.com/wiki/crawler/example/,为了进行一步理解python爬虫的原理,这个基础只之上进一步做出了修改,下面的url可以换成任意的网页,但是编码可能出现问题,

  1. import urllib
  2. import urllib.request
  3. #from html.parser import HTMLParser
  4. from html.parser import HTMLParser
  5. #print(dir(HTMLParser))
  6. import re
  7. import requests
  8. import time
  9. #print(dir(urllib.request.urlopen.__dict__))
  10. class MovieParser(HTMLParser): #定义电影解析器
  11. def __init__(self):
  12. HTMLParser.__init__(self) #调用父类的构造函数
  13. self.movies = [] #定义一个数组来保存电影,默认为空
  14. def handle_starttag(self,tag,attrs): #重载这个方法,去解析li这个数据
  15. # tag 是标签 attrs是属性列表[(属性,对应属性的值),...],元组的列表
  16. #print("Done!'\n")
  17. #print(tag,attrs)
  18. print(" tag : {0} | attrs : {1}\n".format(tag,attrs))
  19. def _attr(attrlist,attrname):#定义一个函数来解析属性
  20. #time.sleep(10)
  21. for attr in attrlist:
  22. #print(attr,attr[0],attrname)
  23. if attr[0] == attrname: #如果这个属性名称和要求的一样
  24. #print(attr[1])
  25. return attr[1] #返回属性的值
  26. return None #如果没有找到返回空
  27. if len(attrs)>0:
  28. #print(" tag : {0} |attrs : {1}\n".format(tag, attrs))
  29. if tag == 'li' and _attr(attrs,'data-title') is not None:
  30. #print(attrs)
  31. movie = {}
  32. movie['title'] = _attr(attrs,'data-title') #电影名称
  33. movie['score'] = _attr(attrs,'data-score') #电影分数
  34. movie['director'] = _attr(attrs,'data-director') #电影导演
  35. movie['actors'] = _attr(attrs,'data-actors') # 电影演员
  36. self.movies.append(movie) #提取出的电影放到列表里面
  37. #print('%(title)s|%(score)s|%(director)s|%(actors)s' % movie)
  38. print('%(title)s|%(score)s|%(director)s|%(actors)s' % movie)
  39. def nowplaying_movies(url):
  40. #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'} #
  41. headers = {
  42. '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'}
  43. #请求头
  44. #模拟一个浏览器的行为
  45. #req = urllib.request(url, headers=headers) #定制一个http头
  46. print(url)
  47. #s = urllib.request.urlopen(url) #获取这个请求
  48. s = requests.get(url,headers=headers)
  49. s.encoding = 'utf-8' #防止发生编码错误
  50. #print(s.read()) # 读取得是字节类型,必须进行解码
  51. parser = MovieParser() #解析器
  52. #print(s.content.decode('utf-8')) #解码之后得到整个h网页得代码,里面有我们需要得内容
  53. # 使用utf-8进行解码
  54. parser.feed(s.content.decode())
  55. #s.close()
  56. return parser.movies #把解析器里面的movies返回给调用者
  57. if __name__ == '__main__':
  58. #url = 'http://movie.douban.com/nowplaying/xiamen/' #豆瓣热播电影的地址,还有分城市
  59. url = 'http://www.maiziedu.com/wiki/crawler/multi/'
  60. movies = nowplaying_movies(url) #定义一个函数nowplaying_movies,就是当前正在热播的电影,我们希望这个函数传进去就是url,还会就是一个电影列表
  61. import json
  62. #json 默认使用ASCII编码,所以不显示汉字
  63. print('%s' % json.dumps(movies, ensure_ascii=False,sort_keys=True, indent=4, separators=(',', ': '))) # 这个电影列表通过 json把它编码一下,打印出来
  1. <!DOCTYPE html>
  2. <html lang="zh-cmn-Hans" class="ua-windows ua-webkit">
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  5. <meta name="renderer" content="webkit">
  6. <meta name="referrer" content="always">
  7. <meta name="google-site-verification" content="ok0wCgT20tBBgo9_zat2iAcimtN4Ftf5ccsh092Xeyw" />
  8. <title>
  9. 厦门 - 在线购票&amp;影讯
  10. </title>
  11. <meta name="baidu-site-verification" content="cZdR4xxR7RxmM4zE" />
  12. <meta http-equiv="Pragma" content="no-cache">
  13. <meta http-equiv="Expires" content="Sun, 6 Mar 2005 01:00:00 GMT">
  14. <meta name="keywords" content="厦门,在线购票,网上电影票预订,优惠电影票,影讯,排片,放映时间,电影票价"/>
  15. <meta name="description" content="厦门电影院在线优惠购票及影讯排片查询"/>
  16. <link rel="apple-touch-icon" href="/pics/movie/apple-touch-icon.png">
  17. <link href="https://img3.doubanio.com/f/shire/52c9997d6d42db58eab418e976a14d5f3eff981e/css/douban.css" rel="stylesheet" type="text/css">
  18. <link href="https://img3.doubanio.com/f/shire/ae3f5a3e3085968370b1fc63afcecb22d3284848/css/separation/_all.css" rel="stylesheet" type="text/css">
  19. <link href="https://img3.doubanio.com/f/epstein/85f16e2319c370ecd16bbca53d5d006adaa99728/css/movie/base/init.css" rel="stylesheet" type="text/css">
  20. <script type="text/javascript">var _head_start = new Date();</script>
  21. <script type="text/javascript" src="https://img3.doubanio.com/f/epstein/0495cb173e298c28593766009c7b0a953246c5b5/js/movie/lib/jquery.js"></script>
  22. <script type="text/javascript" src="https://img3.doubanio.com/f/shire/1316664523258f7b8b536e4ce45afc9cb37b8963/js/douban.js"></script>
  23. <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),这样就可以通过遍历进行匹配了。下面我们打印出来就一目了然了。

  1. 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')]
  2. 哪吒之魔童降世|8.6|饺子|吕艳婷 / 囧森瑟夫 / 瀚墨
  3. tag : ul | attrs : [('class', '')]
  4. tag : li | attrs : [('class', 'poster')]
  5. tag : a | attrs : [('href', 'https://movie.douban.com/subject/26794435/?from=playing_poster'), ('class', 'ticket-btn'), ('target', '_blank'), ('data-psource', 'poster')]
  6. tag : img | attrs : [('src', 'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2563780504.jpg'), ('alt', '哪吒之魔童降世'), ('rel', 'nofollow'), ('class', '')]
  7. tag : li | attrs : [('class', 'stitle')]
  8. tag : a | attrs : [('href', 'https://movie.douban.com/subject/26794435/?from=playing_poster'), ('class', 'ticket-btn'), ('target', '_blank'), ('title', '哪吒之魔童降世'), ('data-psource', 'title')]
  1. [
  2. {
  3. "actors": "唐国强 / 刘劲 / 黄景瑜",
  4. "director": "黄建新 宁海强",
  5. "score": "7.0",
  6. "title": "决胜时刻"
  7. },
  8. {
  9. "actors": "黄渤 / 张译 / 吴京",
  10. "director": "陈凯歌 张一白 管虎 薛晓路 徐峥 宁浩 文牧野",
  11. "score": "0",
  12. "title": "我和我的祖国"
  13. },
  14. {
  15. "actors": "平采娜·乐维瑟派布恩 / 奈哈·西贡索邦 / 杰森·杨",
  16. "director": "查亚诺普·布恩帕拉科布",
  17. "score": "6.6",
  18. "title": "友情以上"
  19. },
  20. {
  21. "actors": "山新 / 郝祥海 / 刘明月",
  22. "director": "木头",
  23. "score": "8.2",
  24. "title": "罗小黑战记"
  25. },
  26. {
  27. "actors": "吴京 / 章子怡 / 张译",
  28. "director": "李仁港",
  29. "score": "0",
  30. "title": "攀登者"
  31. },
  32. {
  33. "actors": "肖战 / 李沁 / 孟美岐",
  34. "director": "程小东",
  35. "score": "5.3",
  36. "title": "诛仙 Ⅰ"
  37. },
  38. {
  39. "actors": "任达华 / 梁咏琪 / 罗仲谦",
  40. "director": "罗永昌",
  41. "score": "6.9",
  42. "title": "小Q"
  43. },

python异步爬虫-下拉网页爬取

以知乎问答为例,对于其他的网页比如今日头条和淘宝美团点评也类似,

 打开https://www.zhihu.com/question/21400402,打开浏览器检查->网络->XHR

 

首先找到这个问题下第一个回答对应的url连接,见上图第一个空色方框,由于一个网页可以容纳的回答有限,这里总共有225个回答,鼠标往下滚动刷新,发现最左边的内容变多了,我们通过第一个url只能获取5个回答,那么如何获取所有的回答呢,如果我们能发现所有url的规律不是可以了?

通过分析表头的url参数可知不同的回答有个offset参数不一样其他都是一样的,直接循环一下就好了,当然由于不同的前段方法有些参数也可以是page或者其他

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号