爬虫进阶(一)

    技术2022-07-11  99

    爬虫进阶(一)

    前言

    ​ 实在是太辣鸡了,写个爬虫用了大半天,各种错误都有,这还是很小的项目,一个人搞得大项目那是真滴累,队里其他大佬都准备去线下了,弱鸡只能敲敲代码的分,得加油学习了。。。此次针对的是爬取的不同用户的用户ID、粉丝数量、点赞数、评论数和阅读数,并且和本地数据库交互,将爬到的数据存放在数据库中,emmmm有一个小问题就是没有涉及去重的算法,本来想在数据库中去重,但是爬一个查一遍数据库实在是浪费资源,索性没有去重了,不过大部分情况下还是不会有重复的。

    正言

    本来想利用BeautifulSoup类的,但是后来发现一个真香的 etree,是在python第三方库的 lxml中,这是HTML的解析器,关于解析器的优劣列了张图:

    之前用的标准库,目前爬虫都是轻量级,也没开什么线程,体验不到有何区别23333。

    但是BeautifulSoup是在没有etree香,所以这里说明一下etree

    lementTree轻量级的 Python 式的 API ,它由一个 C 实现来提供。相对于 DOM 来说,ET 快了很多而且有很多令人愉悦的 API 可以使用。

    在这里是通过xpath来查找路径的

    XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。 XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 都构建于 XPath 表达之上。

    从上面这句话我们可以看出来, xpath 是用来查找 XML ,而我们的 HTML 可以认为是语法不标准的 XML 文档,恰巧我们可以通过这种方式来解析 HTML 文档。

    我们在使用 xpath 之前,需要先安装 xpath 的依赖库,这个库并不是 Python 提供的标准库,安装语句如下:

    pip install lxml

    xpath的简单语法如下:

    如果嫌麻烦的话,在Chrome中右击检查查找到相应的html时右击有copy选项,可以copy出特定的xpath,十分方便。

    例如当我copy得到xpath路径后,通过如下语句:

    fans_num = str(etree.HTML(html_csdn).xpath('//*[@id="fan"]/text()')[0]) #html_csdn是get请求得到的text文本,得到了粉丝数(注意返回的是列表)

    连接数据库

    python提供了第三方库可以连接mysql

    pip install pymysql

    通过pymysql.connect开启连接,然后获取操作游标后,写好sql请求,最后提交在关闭即可,具体的语法大伙可以自己搜搜,挺简单的,连本菜鸟都会用了,因为爬虫只负责一个数据爬取工作,所以只需要一句 insert 语句就够了。

    最终代码:

    #coding=utf-8 import re import requests import pymysql from bs4 import BeautifulSoup from lxml import etree import time headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36' } def get_data(url): res = requests.get(url,headers=headers) html_csdn = res.text # to crawl csdn data including these: read_num = str(etree.HTML(html_csdn).xpath('//*[@id="asideProfile"]/div[2]/dl[5]/dt/span/text()')[0]) fans_num = str(etree.HTML(html_csdn).xpath('//*[@id="fan"]/text()')[0]) likes_num = str(etree.HTML(html_csdn).xpath('//*[@id="asideProfile"]/div[2]/dl[3]/dt/span/text()')[0]) author = str(etree.HTML(html_csdn).xpath('//*[@id="uid"]/span/@username')[0]).replace(" ","").replace("\n","") comment_num = str(etree.HTML(html_csdn).xpath('//*[@id="asideProfile"]/div[2]/dl[4]/dt/span/text()')[0]) return {"userID":author,"read_num":read_num,"fans_num":fans_num,"likes_num":likes_num,"comment_num":comment_num,"url":url} def connect(): #connect database conn = pymysql.connect( host = 'localhost', port = 3306, user = 'root', password = 'root', database = 'data', charset = 'utf8mb4' ) #Get a cursor object that can execute SQL statements cursor = conn.cursor() return {"conn":conn,"cursor":cursor} connection = connect() conn = connection['conn'] cursor = connection['cursor'] #insert data into database def sqlinsert(): sql_insert = "insert into (userID,read_num,fans_num,likes_num,comment_num) values ('{userID}','{read_num}','{fans_num}','{likes_num}','{comment_num}');".format(**data) cursor.execute(sql_insert) conn.commit() # judge if url is valid and not repeated def continue_crawl(url_list,max_steps=5): if(len(url_list) > max_steps): print("already crawl so many~") return False elif(url_list[-1] in url_list[:-1]): print("already crawl it!") return False else: return True all_url = [] # get next url and put it in list def get_url(url): res = requests.get(url,headers=headers) html = res.text all_url = re.findall('<.*?href="(https://blog.csdn.net.*?)".*?',html) return all_url[-4] # all you need change is here ,change the first url in url_list url_list = ['https://blog.csdn.net/crisprx/article/details/107048541'] while continue_crawl(url_list,20): data = get_data(url_list[-1]) sqlinsert() next_url = get_url(url_list[-1]) url_list.append(next_url) print(url_list[-1]) time.sleep(2) cursor.close() conn.close()

    再贴一个最终的效果图

    和数据库的图:

    同样会git到github的,请大伙没事点个star~~

    Processed: 0.010, SQL: 9