4

作者:xiaoyu
微信公众号:Python数据科学
知乎:Python数据分析师


<10>

海贼王已经10年了,一路陪伴了我们的点点滴滴。它热血,激情,感人,欢乐,吸引了无数男女老少的紧紧跟随。
说起来还真有点小心酸,原谅博主也是个海贼迷,心中怀揣着很大的梦想,誓死也要成为海贼王的男人。
但如今梦想已经破灭了,因为博主有了女朋友...

clipboard.png

什么?说我是假粉丝,我上去就给你一巴掌!看到最后你就知道什么叫真粉儿!!

clipboard.png

好了,收!

爬取目标

说说我们的正题,前面两篇爬虫学习介绍了正则BeautifulSoup的内容,这里其实是想借着这个机会给大家分享一下正则BeautifulSoup解析的实战例子。

目标实现比较简单,就是下载xxx网站上海贼王动漫的套图。爬取效果如下:

clipboard.png
(截取了部分下载过程)

clipboard.png
(部分下载图片)

采取了多线程爬取,总共1000多张,都存在本地了。

功能分析

本篇目的是使用正则+BeautifulSoup,因此后面不更多赘述了。

提取系列链接

clipboard.png

通过开发者工具看到,所有的系列都是同一级别的节点,那么我们首先应该做的是遍历所有页码,然后提取每页各个系列的链接。

接下来看看链接在哪。

clipboard.png
小提示:红框内第一个是鼠标自动跟随,第二个是手机/PC切换,使用起来非常方便。

具体点开其中一个系列标签一看,我们要的链接正是<a>标签下的href属性,但是你会发现有两个一模一样的href属性,链接也一样,而我们只需要一个,这就需要小处理一下了,提供两个思路:

  • 使用BeautifulSoup方法单独提炼出一个链接
  • 两个链接都提炼出来,放进set集合中去重

这里博主用的第一种方法。

提取系图片链接

clipboard.png

同样的过程,图片的链接在<p>标签下的子节点<img>的src属性里,依然使用BeautifulSoup就可轻松解决。

但是这里的网页排版有个问题,就是有的系列中多组图在一页中,而有的系列每页只有一张图,需要翻页查看。

解决方法是不管有没有翻页,都直接遍历该系列下的所有页,通过返回的状态码来判断下一步动作。

好了,解析的任务的分析差不多完成了,下面看看具体代码如何实现的。

代码实现

下载系列链接:

def html_parse(self, num):
    try:
        url_make = self.url.format(num)
        html = requests.get(url_make, timeout=10)
        soup = BeautifulSoup(html.content, 'lxml')
        ul_tag = soup.find_all('ul', class_='spic pic1')
        soup1 = BeautifulSoup(str(ul_tag[0]), 'lxml')

        for counter, li_tag in enumerate(soup1.find_all('li')):
            soup2 = BeautifulSoup(str(li_tag), 'lxml')
            a_tag = soup2.find_all('a')
            href_list = re.findall(re.compile('href="(.+?)"'), str(a_tag))
            if len(href_list) != 0:
                print('第 ' + str(num) + ' 页: ----第 ' + str(counter + 1)
                      + '个链接:' + href_list[0] + ' ----')
                self.q.put(href_list[0])
        sleep(random.randint(2, 3))
    except requests.ConnectionError:
        pass

下载图片链接:

 def picture_parse(self):
        try:
            sub_url = self.q.get()
            sub_url_base = sub_url[:-6]
            for page in range(1, 10):
                sub_url_new = sub_url_base + '_' + str(page) + '.shtml'

                html2 = requests.get(sub_url_new)
                if html2.status_code == 200:
                    soup = BeautifulSoup(html2.content, 'lxml')
                    div_tag = soup.find_all('div', id='pictureContent')
                    soup1 = BeautifulSoup(str(div_tag[0]), 'lxml')

                    for img_tag in soup1.find_all('img', src=re.compile('.+?')):
                        soup3 = BeautifulSoup(str(img_tag), 'lxml')
                        if soup3.img['src'] is not None:
                            self.picture_link.append(soup3.img['src'])
                            print(str('----' + soup3.img['alt']) + '链接 : '
                                  + str(soup3.img['src']) + ' ----')
                    sleep(random.randint(2, 3))
                else:
                    pass
        except requests.ConnectionError:
            pass

下载并储存图片到本地:

 def picture_store(self):
    try:
        for num, link in enumerate(set(self.picture_link)):
            html3 = requests.get(link)
            picture_path = 'D:\Pictures_Downloaded\\' + 'pic' + str(num+1) + '.jpg'
            with open(picture_path, 'wb') as f:
                f.write(html3.content)
    except requests.ConnectionError:
        pass

多线程队列任务:

def main(self):
    page_num = 2
    threads_0 = []
    for i in range(1, page_num):
        t = Thread(target=self.html_parse, args=(i,), name='Thread-0')
        threads_0.append(t)
    for i in range(len(threads_0)):
        threads_0[i].start()
    for i in range(len(threads_0)):
        threads_0[i].join()

    threads_1 = []
    for i in range(self.q.qsize()):
        t1 = Thread(target=self.picture_parse, args=(), name='Thread-1')
        threads_1.append(t1)
    for i in range(len(threads_1)):
        threads_1[i].start()
    for i in range(len(threads_1)):
        threads_1[i].join()

    self.picture_store()

注:爬取间隔可以适当再长点,减轻目标服务器的负担,也理解一下辛苦的运维工作人员。

代码比较简单,目的是在实战中掌握正则和BeautifulSoup解析方法,欢迎大家指点和讨论。

完整代码已上传到Github,请参考:https://github.com/xiaoyusmd/...

作品展示

这部分是为了兑现铁粉儿的承诺,不感兴趣可忽略。

博主库爱画画,素描,水彩,国画都学过点,当然这个是在wacom绘画板上,利用corel painter + photoshop完成的。由于热爱海贼王动漫,闲暇时间画了个各种海贼绘画。

以下是几张索隆桑的绘图(无水印),感兴趣的朋友可以收藏:)
图片描述
图片描述
图片描述


关注微信公众号Python数据科学,获取 120G 人工智能 学习资料。

图片描述

图片描述


东哥起飞
3.8k 声望9.3k 粉丝