鱼C论坛

 找回密码
 立即注册
查看: 2283|回复: 3

[作品展示] 结合BeautifulSoup和pymysql编写的MMSpider

[复制链接]
发表于 2017-12-18 15:37:57 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 神奇的yxq 于 2017-12-18 15:50 编辑

为了学习bs4模块,所以将mmspider“高清重置”了一下

前置解释:internet为自制的模块,里面的有两个类 Browser 和 Download ,前者实现Browser.get(url),后者实现下载srcqueue里面下载队列,感兴趣的可以下载附件
                 mylogging为自制模块,里面三个类分别是Logging记录到输入,LoggingText记录到文本文件,LoggingDB记录到数据库,都有一个方法log.put(需要记录的信息, 记录的位置, 记录等级), 感兴趣打附件下载

附件:
游客,如果您要查看本帖隐藏内容请回复



  1. # 需求:下载http://www.mzitu.com/网站的妹子图片
  2. """
  3. 思路:
  4. 1、访问图集首页 如:http://www.mzitu.com/page/页码数/;
  5. 2、获取每个图集的详情页面;
  6. 3、访问每个图集的详情页面 如:http://www.mzitu.com/106245/页码数/;
  7. 4、获取 每页的图片地址;
  8. 5、将每个图集的所有图片的地址打包给downloader下载;
  9. 6、拼接第二个首页地址,返回第一步;
  10. 7、爬取到达到指定的页数或爬取完所有页数 爬虫停止爬取;
  11. """


  12. from bs4 import BeautifulSoup
  13. import internet
  14. import mylogging
  15. import queue


  16. def searchimglist(content):
  17.     """
  18.     用于获取图集的url
  19.     :param content: 返回的数据
  20.     :return: url列表[(图集名, 图集url), ...]
  21.     """
  22.     soup = BeautifulSoup(content, "lxml")
  23.     lilist = soup.find_all("li")
  24.     imglist = []

  25.     for eachli in lilist:
  26.         if len(eachli) == 4:
  27.             temp = eachli.find_all("a")
  28.             url = temp[1].attrs["href"]
  29.             title = temp[1].text
  30.             imglist.append((title, url))

  31.     return imglist


  32. def searchimgurl(content):
  33.     """
  34.     用于搜索和组装图片src
  35.     :param content: 请求的返回数据
  36.     :return: srclist
  37.     """
  38.     soup = BeautifulSoup(content, "lxml")
  39.     title = soup.find_all("h2", {"class": "main-title"})[0].text  # 获取标题
  40.     url = soup.find_all("img", {"alt": title})[0].attrs["src"]  # 获取第一张图片的url
  41.     maxpage = soup.find_all("div", {"class": "pagenavi"})[0].find_all("span")[-2].text  # 获取最大页码数,也是图片数量
  42.     srclist = []

  43.     for pagenumber in range(1, int(maxpage) + 1):  # 组装其他图片的src地址
  44.         if pagenumber < 10:
  45.             pagenumber = "0" + str(pagenumber)
  46.         else:
  47.             pagenumber = str(pagenumber)
  48.         src = url[:-6] + pagenumber + url[-4:]
  49.         srclist.append(src)

  50.     return srclist


  51. def main():
  52.     """
  53.     主函数
  54.     :return: none
  55.     """
  56.     rawurl = "http://www.mzitu.com/page/"  # 原始url
  57.     downloadPath = "MMImg"

  58.     while True:
  59.         maxpage = input("请输入爬虫爬取的最大页数:")
  60.         try:
  61.             maxpage = int(maxpage)
  62.         except ValueError:
  63.             print("输入错误!请重新输入")
  64.         else:
  65.             if maxpage > 150:
  66.                 print("太多了,身体吃不消的!")
  67.                 continue
  68.             else:
  69.                 print("爬取任务:%s 页!爬虫开始爬取" % maxpage)
  70.                 break

  71.     log = mylogging.Logging(name="MMSpider")
  72.     srcqueue = queue.Queue(30)

  73.     b = internet.Browse()  # 浏览器类
  74.     b.__log__ = log

  75.     d1 = internet.Download(srcqueue, downloadPath=downloadPath, downloader=2, downloadWaitTime=1)  # 下载器线程
  76.     d2 = internet.Download(srcqueue, downloadPath=downloadPath, downloader=2, downloadWaitTime=1)
  77.     d3 = internet.Download(srcqueue, downloadPath=downloadPath, downloader=2, downloadWaitTime=1)
  78.     # 讲道理,别搞太多下载器线程
  79.     d1.__log__ = log
  80.     d2.__log__ = log
  81.     d3.__log__ = log

  82.     d1.start()
  83.     d2.start()
  84.     d3.start()

  85.     for i in range(1, maxpage + 1):
  86.         if i < 10:
  87.             i = "0" + str(i)
  88.         else:
  89.             i = str(i)
  90.         url = rawurl + i + "/"  # 组装页面url
  91.         print("正在访问第%s页,url=%s" % (i, url))
  92.         content = b.get(url, decoding=False)

  93.         if  not content:  # 异常处理
  94.             print(content)
  95.             continue

  96.         imglist = searchimglist(content)  # 获取所有图片集标题和地址
  97.         for title, imgurl in imglist:
  98.             print("正在访问[%s]的详情页,url=%s" % (title, imgurl))
  99.             content = b.get(imgurl, decoding=False)

  100.             if not content:  # 异常处理
  101.                 print(content)
  102.                 continue

  103.             srclist = searchimgurl(content)
  104.             datapage = [title, "jpg", imgurl]
  105.             datapage.extend(srclist)
  106.             srcqueue.put(datapage)  # 数据包打包给downloader
  107.             srcqueue.task_done()

  108.     d1.join()
  109.     d2.join()
  110.     d3.join()
  111.     print("MMSpider 爬取完毕!")


  112. main()

复制代码


以上是 直接下载版 ,后期为了学习mysql,所以将之改造成数据采集版:


  1. # 需求:采集http://www.mzitu.com/网站的妹子图片的地址到数据库
  2. """
  3. 思路:
  4. 1、访问图集首页 如:http://www.mzitu.com/page/页码数/;
  5. 2、获取每个图集的详情页面;
  6. 3、访问每个图集的详情页面 如:http://www.mzitu.com/106245/页码数/,并保存到数据库;
  7. 4、获取 每页的图片地址;
  8. 5、将每个图集的所有图片的地址保存到mysql数据库;
  9. 6、拼接第二个首页地址,返回第一步;
  10. 7、爬取到达到指定的页数或爬取完所有页数 爬虫停止爬取;
  11. """

  12. from bs4 import BeautifulSoup
  13. import internet
  14. import pymysql
  15. import mylogging
  16. import urllib.parse


  17. def searchImgList(content):
  18. ...

  19. def searchImgUrl(content):
  20. ...

  21. def getSelectResult(cur, cmd):
  22.     cur.execute(cmd)
  23.     result = cur.fetchall()
  24.     return result


  25. def main():
  26.     """
  27.     主函数
  28.     :return: none
  29.     """
  30.     rawurl = "http://www.mzitu.com/page/"  # 原始url
  31.     maxpage = 150

  32.     mmSpiderDbInfo = {
  33.         "host": "localhost",
  34.         "port": 3306,
  35.         "user": "root",
  36.         "passwd": "789987110",
  37.         "charset": "utf8",
  38.         "db": "mmspiderdb"
  39.     }

  40.     '''logDbInfo = {
  41.         "host": "localhost",
  42.         "port": 3306,
  43.         "user": "root",
  44.         "passwd": "789987110",
  45.         "charset": "utf8",
  46.         "db": "logdb",
  47.         "table": "mmspider"
  48.     }'''

  49.     host = mmSpiderDbInfo["host"]
  50.     port = mmSpiderDbInfo["port"]
  51.     user = mmSpiderDbInfo["user"]
  52.     passwd = mmSpiderDbInfo["passwd"]
  53.     database = mmSpiderDbInfo["db"]

  54.     log = mylogging.Logging()
  55.     b = internet.Browse()
  56.     b.__log__ = log

  57.     try:
  58.         db = pymysql.connect(host=host, port=port,
  59.                              user=user, passwd=passwd,
  60.                              db=database, charset="utf8")
  61.     except pymysql.err.InternalError:
  62.         try:
  63.             db = pymysql.connect(host=host, port=port,
  64.                                  user=user, passwd=passwd,
  65.                                  charset="utf8")
  66.         except Exception as e:
  67.             log.put(e, "MMSpider.main() Create DataBase", "warning")
  68.             exit()
  69.         else:
  70.             cur = db.cursor(cursor=pymysql.cursors.DictCursor)
  71.             cur.execute("CREATE DATABASE mmspiderdb")
  72.             cur.execute("USE mmspiderdb")
  73.     else:
  74.         cur = db.cursor(cursor=pymysql.cursors.DictCursor)

  75.     try:  # 创建title_table表,用于保存title信息
  76.         cur.execute("CREATE TABLE title_table (title_id INT PRIMARY KEY AUTO_INCREMENT, "
  77.                     "title CHAR(80), url CHAR(100))"
  78.                     "CHARACTER SET utf8;")
  79.     except pymysql.Error:
  80.         pass

  81.     try:  # 创建img_table表,用于保存img信息
  82.         cur.execute("CREATE TABLE img_table (img_id INT PRIMARY KEY AUTO_INCREMENT,"
  83.                     "name CHAR(80), src CHAR(100), title_id INT) "
  84.                     "CHARACTER SET utf8;")
  85.     except pymysql.Error:
  86.         pass

  87.     for i in range(1, maxpage + 1):
  88.         if i < 10:
  89.             i = "0" + str(i)
  90.         else:
  91.             i = str(i)
  92.         url = rawurl + i + "/"  # 组装页面url
  93.         print("正在访问第%s页,url=%s" % (i, url))
  94.         content = b.get(url, decoding=False)

  95.          if  not content: # 异常处理
  96.             log.put(content, "访问列表")
  97.             continue

  98.         imglist = searchImgList(content)  # 获取所有图片集标题和地址
  99.         for (title, url) in imglist:

  100.             cmd = "SELECT title_id, url from title_table WHERE title = '%s';" % title
  101.             result = getSelectResult(cur, cmd)

  102.             if not result:
  103.                 try:
  104.                     cur.execute("INSERT INTO title_table (title, url) "
  105.                                 "VALUES ('%s', '%s')" % (title, url))  # 插入数据到数据库
  106.                     db.commit()
  107.                 except pymysql.Error as e:
  108.                     log.put(e, "MMspider 插入标题", "abnormal")
  109.                     continue

  110.             print("正在访问[%s]的详情页,url=%s" % (title, url))
  111.             content = b.get(url, decoding=False)

  112.             if not content:  # 异常处理
  113.                 log.put(content, "MMspider 访问详情页", "abnormal")
  114.                 continue

  115.             srclist = searchImgUrl(content)

  116.             cmd = "SELECT title_id from title_table WHERE title = '%s'" % title  # 查询,重复的数据不保存
  117.             result = getSelectResult(cur, cmd)  # 获取title的id
  118.             title_id = result[0]["title_id"]

  119.             cmd = "SELECT src from img_table WHERE title_id = '%s'" % title_id  # 查询,重复的数据不保存
  120.             result = getSelectResult(cur, cmd)
  121.             for src in srclist:
  122.                 if {"src": src} not in result:
  123.                     name = urllib.parse.urlparse(src)[2].split("/")[-1]
  124.                     try:
  125.                         cur.execute("INSERT INTO img_table (name, src, title_id)"
  126.                                     "VALUES ('%s', '%s', %d)" % (name, src, title_id))
  127.                         db.commit()
  128.                     except Exception as e:
  129.                         log.put(e, "MMSpider", "warning")
  130.                         continue

  131.     db.close()
  132.     log.close()
  133.     print("MMSpider 爬取完毕!")


  134. main()
复制代码



附带一个爬取妹子自拍的爬虫:


  1. import internet
  2. from bs4 import BeautifulSoup


  3. b = internet.Browse()
  4. d = internet.Download(downloadPath="zipai", downloader=2, downloadWaitTime=2)
  5. d.start()

  6. maxpage = 317

  7. for i in range(1, maxpage + 1):
  8.     url = "http://www.mzitu.com/zipai/comment-page-%s/#comments" % i
  9.     print("正在访问第 %d 页|url=%s" % (i, url))

  10.     content = b.get(url, decoding=False)
  11.     soup = BeautifulSoup(content, "lxml")

  12.     imglist = soup.find_all("img")

  13.     srclist = []
  14.     for each in imglist:
  15.         src = each.attrs["src"]
  16.         srclist.append(src)

  17.     datapage = [".", "jpg", url]
  18.     datapage.extend(srclist)
  19.     d.srcQueue.put(datapage)
  20.     d.srcQueue.task_done()
复制代码


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-12-18 22:14:54 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-1-11 15:31:41 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-1-11 17:06:30 | 显示全部楼层
好东西
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-3-28 16:15

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表