个性化面向对象分类爬虫

Robin 9867次浏览

摘要:有意想整个图片采集站,有了这个想法接下来就是实践了,空间域名啥的都买了,今天写的这个是采集美图网站的

环境:Windows

工具:PyCharm

版本:Python3.6

模块:requests、lxml、pymysql、time


我们会在首页、列表页、分类页、内容页多次用到requests.get()方法,所以简单的封装一下

def getHtml(self, url, is_xpath = True):
    try:
        html = requests.get(url).text
    except:
        print('--------HTTP ERROR: %s--------' % url)
        return False
    if is_xpath:
        return etree.HTML(html)
    else:
        return html

is_xpath用来区分直接返回网页源码还是返回经过处理的直接用xpath匹配的。


因为多个地方要把数据入库所以封装个数据插入的方法:

def saveSQL(self, table, data, More = False):
    insert_id = int()
    if table == 'album':
        sql = "INSERT INTO album (cate_id, title, thumb, url, time, create_time) \
               VALUES (%d, '%s', '%s', '%s', '%s', %d)"
    elif table == 'album_info':
        sql = "INSERT INTO album_info (album_id, url, create_time) \
               VALUES (%s, %s, %s)"
    try:
        if not More:
            self.cursor.execute(sql % data)
        else:
            self.cursor.executemany(sql, data)
        insert_id = int(self.connect.insert_id())
        self.connect.commit()
    except:
        self.connect.rollback()
    return insert_id

More来区分是插入一条还是插入多条。


因为分类很多,每个分类下的页数也很多,所以打算分开来抓,那么我们就按输入的分类和页数来执行爬虫

if __name__ == '__main__':
    spider = Spider()
    cate_id, pages = spider.choiceCate()
    if not cate_id or int(cate_id) > 10:
        print('The input category does not exist, Please try again!')
        cate_id = spider.choiceCate()
    spider.run(cate_id, pages)


在spider类中,定义了choicCate()方法,此方法就是让用户开输入分类和页数的,只做了对分类错误的处理,其中10代表了现在的10个分类,

在这里我没有去做错误次数的限制,想加的可以加上。下面是choicCate()方法:

def choiceCate(self):
    print("1.性感美女 2.丝袜美腿 3.唯美写真 4.网络美女  5.高清美女\n6.模特美女 7.体育美女 8.动漫美女 9.女星写真 10.男星图片")
    cate_id = input('Please enter the classification number to be crawled: ')
    pages = input('Please enter the pages to be crawled: ')
    return cate_id, pages


run()就是我们的主函数了,根据用户输入的分类和页数执行爬虫

def run(self, cate_id, pages):
    print('---------------Began to crawl: %s ---------------' % self.cates[cate_id][1])
    for page in range(1, int(pages) + 1):
        print('------------------Began pages %d-----------------' % page)
        tree = self.getHtml(self.url + self.cates[cate_id][0] + 'index-' + str(page) + '.htm')
        if tree:
            images = self.getInfo(tree, cate_id)
            print('------------Page %d crawl to complete.------------' % page)


getInfo()方法获取分类下所有的缩略图和名称和内容页链接,获取到后存入mysql,根据内容页链接继续获取所有内容页的的图片

def getInfo(self, tree, cate_id):
    items = tree.xpath('//div[@class="piclist"]/ul/li')
    for item in items:
        url = item.xpath('a/@href')[0]
        title = item.xpath('a/span/text()')[0]
        thumb = item.xpath('a/img/@src')[0]
        time = item.xpath('b[1]/text()')[0]
        album = (int(cate_id), title, thumb, url, time, self.getTimestamp())
        print('------------------Began %s------------------' % title)
        info_id = self.saveSQL('album', album)
        images = self.getInfoImages(self.url + url, info_id)
        print('------------------End %s------------------' % title)
    return True


getInfoImages()方法就是来获取内容页详情图并存入mysql的

def getInfoImages(self, url, info_id):
    tree = self.getHtml(url)
    if tree == False:
        return False
    tags = tree.xpath('//div[@class="picbottomline"]/p[1]/span/a/text()')
    tags = ','.join(tags)
    self.updateSQL('album', "tags = '" + tags + "'", 'id = ' + str(info_id))
    base_info = url[:url.rfind('/')]
    page_url = base_info + '.htm'
    images = self.getImagesUrl(page_url)
    images_data = []
    for image in images:
        images_data.append([int(info_id), image, self.getTimestamp()])
    self.saveSQL('album_info', images_data, True)
    return True

因为在分类页没有显示tags标签,只有在内容详情页才有,所有还需要更新下之前的表,updateSQL()就是这个功能,下面我们看看执行的效果吧,效果如下:

QQ截图20180119142752.jpg

image.png


原创文章转载请注明出处。

相关文章