引言

我写的这个爬虫非常的简单,没有什么难的逻辑思维,只是简单运用BeautifulSoup进行爬取,相信初学者都可以看懂,就是代码写的比较乱,因为我也是初学者。。。。可能你没有耐心看完,我会尽量一部分一部分地分开讲解,尽量让大家看起来不会觉得脑袋大,只要你带着一种这个文章很简单很容易懂的潜意识去阅读,那你一定能够轻松看懂的,不要被还没开始便畏难的潜意识所打败。

需要准备的库以及网页链接:

  requestsBeautifulSouprandomrehttps://www.amazon.cn/gp/book/all_category/ref=sv_b_1

requests库主要是用于发送网络请求
BeautifulSoup库我用的最多,用于匹配我需要的数据
random库没有什么用处,只是为了防止爬取亚马逊网页的时候被反爬虫,所以弄了一个随机获取请求头的方法
re库在这次实验中很少一部分用到了它,主要是用于爬取一些数据,但是也算是给我涨了一点新知识,因为大部分同学都说正则表达式来匹配数据比BeautifulSoup更简单
关于相关库的介绍我就不啰嗦了,相信大家只要一百度都可以找到,而且这些库都说爬虫基础的,没有什么安装困难
最后的一个链接便是我使用的亚马逊书城的链接

我想实现的功能

  • 实现一级、二级目录的展示,目录是根据书籍类型分类的,由一级大目录到二级目录再到准确的书籍
  • 由目录找到书籍列表,并且把当前页展示的书籍的简单介绍信息排列出来同时进行编号,如果当前页有副页,则可以实现页码的翻页
  • 在停止翻页后会进行确切一本书的查找,用户只需要输入上面排列出的书籍中对应的编号就可以查看那本书的相关信息(包括书名、作者、出版社、书籍编码、评论等)
  • 同时还会在书籍详细介绍中显示出书籍的星级评论百分比分布以及其对应的前十条相关评论(有的评论上百条,所以这里没有进行翻页处理,只读取当前评论第一页的内容)。

代码的主要框架展示



虽然我的命名不是很规范,但是相信大家根据我的中文注释也大概知道了每个方法执行者怎么样的操作,接下来我便会跟大家慢慢讲解我的代码中一些实现的细节部分。

代码讲解部分

  1. randHeader部分我就不讲太多了,相信只要大家需要什么样的请求头,直接百度都可以出现。
  2. outPrintMessage这个方法也没事什么可将的,只是用于输出一些提示信息,把不重要的部分从主要代码中提取出来另外分装,让主要的代码看起来没有那么冗长
#打印出菜单
def outPrinMessage(num):if num == 1:print("+-----------------+")print("+                 +")print("+ 欢迎光临亚马逊书城 +")print("+                 +")print("+-----------------+")
  1. getHtmlText这是方法是用于请求网页以后,返回一个text文本。r.raise_for_status()作用在于,当我们发出一个错误的请求的时候,这句代码会给我们抛出一个异常。这个方法也是简单到不行,我相信大家一定可以看懂。
#获取请求后的网页内容
def getHtmlText(url):headers = randHeader()try:r = requests.get(url, headers = headers, timeout=30)#获取连接并设置了连接的超时时间为30秒r.raise_for_status()r.encoding = 'utf-8'return r.textexcept:return '请检查网络是否连接成功'
  1. findAllItems(soup)用于查找并列出一级目录,同时找到一级目录下对应的二级目录分类以及url地址,方便后期的跳转网页请求
    分析: 我们可以清晰看到原网页上面,我想要的一级目录和二级目录是在同一页上面,左边的一个一级目录对应着右边的一个一级目录,因此我们需要同时获取一级目录和耳机目录以及二级目录对应的每个url地址,那我们应该怎么做呢?
    我们可以定义一个list(itemName)来保存一级目录,然后在定义一个list(tableItem)来保存二级目录,不过保存二级目录的那个list里面所存的元素是一个字典,因为我们需要同时保存二级目录的目录名以及url地址。并且通过这样的保存,我们可以把一级目录的下标与耳机目录的下标对应起来,这样输入一级目录的时候,我们就可以很方便得找到当前类型下所有的二级目录。

    largeItem用于查找到一级目录列表
    littleItem用于查找装载二级目录的那个范围框
        for i in littleItem:dic = {}iUrl = i.find_all('a', attrs={'class': 'a-link-nav-icon'})for j in iUrl:name = j.get("title")  # 查找到大分类里面的小分类名称url = j.get('href')  # 查找到小分类的地址dic[name] = urltableItem.append(dic)

iUrl是用于找到装载了二级目录的范围框内所有的二级目录。

        if largeItem != None:print(" |", end=" ")for item in largeItem:div = item.find('a').get('title')itemsName.append(div)print(div, end=" | ")print("\n")return itemsName, tableItemreturn None, None

得到一级目录的名称,然后打印出来,实现的效果如下

  1. findUrl(strType,largeItem,items)找到用户输入二级目录类型后对应的网页信息输入的strType是在一级目录里面进行查找,查找到对应的类型后再找出二级目录的目录列表,如果没有查找到会提醒用户重新输入,在代码的第一个for循环里面便是执行这样的操作
    二级列表打印在输出栏后要求用户再次进行书籍类型的赛选,如果找到了就进行网页的跳转,没有找到的话还是会要求用户重新输入。最后返回一个经过requests发出请求后得到的 text文本
#找到用户输入二级目录类型后对应的网页信息
def findUrl(strType,largeItem,items):dic = {}for i in largeItem:if strType == i:dic = items[largeItem.index(i)]breakelse:#找不到输入的类型时返回None提示用户重新输入return Noneprint("\n| ",end=" ")for item in dic.keys():print(item + " | ", end="")print("\n")flag = 0url = Nonewhile flag == 0:#当用户输入错误时提示错误并且要求重新输入try:cho = input("请根据上面的列表输入你的搜索关键词:\n")# cho = '名家作品及欣赏'url = dic[cho]  # 从字典中查找到对应的url地址except KeyError:print("\n查询失败!",end="")else:flag = 1rs = getHtmlText(url)return rs
  1. bookList(bookSoup)既然都已经跳转到了有图书列表的页面了,那我们接下来应该做的是什么操作呢?
    还是先给大家看一下当前操作下对应于的亚马逊的网页比较好,让大家先思考一下。比如说现在我选的是 小说->侦探、推理、悬疑小说。网页太大了,没有截完,只截取一部分,现在我就想要求图书像这样竖着排列出来,并且列举出每本图书对应的基本信息
#找到当前页面所有图书的基本信息然后打印到输出栏
def bookList(bookSoup):bookUrl = []index = 0bookLi = bookSoup.find_all('li',attrs={'class':'s-result-item celwidget '})print("-------------------------------------------------------------------------------------------------------------------\n")for li in bookLi:index += 1bookDiv = li.find('div', attrs={'class':'a-fixed-left-grid-col a-col-right'})book_a = bookDiv.find('a',attrs={'class':'a-link-normal s-access-detail-page s-color-twister-title-link a-text-normal'})print('*',index," ",book_a.get('title'),' *')#显示书籍名称author = li.find('div',attrs={'class':'a-row a-spacing-small'}).find_all('div',attrs={'class':'a-row a-spacing-none'})[-1].textprint('作者:',author)#显示书籍作者bookUrl.append(book_a.get('href'))bookType_one = bookDiv.find('div',attrs={'class':'a-column a-span7'}).find_all('div',attrs={'class':'a-row a-spacing-none'})for one in bookType_one:#找到对应书籍的相关信息print(one.text)print("-------------------------------------------------------------------------------------------------------------------\n")return bookUrl

先用bookLi找到所有书单,然后再对书单列表进行遍历,分别去除书籍的名称、作者以及相关信息,这是一段很简单的代码,似乎只要找到相应的位置就能通过BeautifulSoup进行数据获取,效果展示如图(部分截取):

7.ChoosePage(bookSoup,pageTol) 现在我们遇到了一个问题,就是当你把有显示列表的网页滑到底部,你会发现还有翻页的操作,那对于这个我们应该怎么处理呢?我先简单的介绍一下我的思路,主要就是多在网页上面点击几次不同的页码,看看网页进行跳转的时候,顶部的url地址变化有没有什么规律,有的网页的规律是只改变页码的那个编号,但是我观察亚马逊的时候发现,它是没有这个规律的,随着页码的变化它的url地址变化的不只是亚麻的那个编号,我也尝试过在顶部的url那里只更改它的页码,但是不能进行相应页码的跳转。所以我选择了查看网页的源代码。
很明显地可以看出,在截图中能进行网页跳转的知识那些蓝色的部分,这说明是有超链接存在的,所以我们只需要获取蓝色部分的超链接地址,实现与截图中相同的跳转功能即可。
打开检查功能查看网页代码,发现页码超链接会保存在一个pagnLink,所以我们可以获取所有的pageLink然后进行页码url的分配,给每个显示的页码分配相应的url地址
但是我们还是有需要注意的部分:因为它页码显示格式的问题,在获取页码对应的url的时候会有问题,细节我就不详细说了,代码中我划分得特别详细
还有值得一提的就是,在最后几页的时候,网页中会缺少一个TotalPage的部分,所以我们不能直接在这个函数里面获取,而是应该在这个的函数外获取,然后传进这个函数。因为TotalPage我会在后面分析页码格式的时候使用,所以必须得获取。
接下来贴上我的代码:以上代码可以很简单得看出我对特殊页码的处理,如果你去打开检查工具你也会发现相同的特殊格式,接下来是贴上全部展开的代码

    for page in pageNear:count += 1pageNearNum.append(page.find('a').text)pageNearUrl.append(page.find('a').get('href'))dicUN[page.find('a').text] = page.find('a').get('href')if pageCur == '1':#当前页等于1的时候的特殊处理print('< '+'\033[1;31;0m'+pageCur+'\033[0m'+" "+pageNearNum[0]+" "+pageNearNum[1]+" ... "+pageTol+' 下一页 >')NextPageUrl = footPage.find('a',attrs={'class':'pagnNext'}).get('href')elif pageCur == '2':#当前页等于2的时候的特殊处理print('< 上一页 ' + pageNearNum[0] + " " + '\033[1;31;0m' + pageCur + '\033[0m' + " " + pageNearNum[1] + " ... " + pageTol + ' 下一页 >')NextPageUrl = footPage.find('a', attrs={'class': 'pagnNext'}).get('href')PrePageUrl = footPage.find('a', attrs={'class': 'pagnPrev'}).get('href')elif pageCur == '3':#当前页等于3的时候的特殊处理print('< 上一页 '+pageNearNum[0]+" "+ pageNearNum[1] + " " +'\033[1;31;0m'+pageCur+" "+ '\033[0m'+pageNearNum[2]+" ... "+pageTol+" 下一页 >")NextPageUrl = footPage.find('a',attrs={'class':'pagnNext'}).get('href')PrePageUrl = footPage.find('a', attrs={'class': 'pagnPrev'}).get('href')elif pageCur == str(int(pageTol) - 1):#对倒数第二页的特殊处理print("< 上一页 " + pageNearNum[0] + " ... " + pageNearNum[1] + " " + '\033[1;31;0m' + pageCur + " " + '\033[0m' + pageNearNum[2] + " 下一页 >")NextPageUrl = footPage.find('a', attrs={'class': 'pagnNext'}).get('href')PrePageUrl = footPage.find('a', attrs={'class': 'pagnPrev'}).get('href')elif pageCur == str(int(pageTol) - 2):print('< 上一页 ' + pageNearNum[0] + " ... " + pageNearNum[1] + " " + '\033[1;31;0m' + pageCur + " " + '\033[0m' + pageNearNum[2] + " 下一页 >")count -= 1NextPageUrl = footPage.find('a', attrs={'class': 'pagnNext'}).get('href')PrePageUrl = footPage.find('a', attrs={'class': 'pagnPrev'}).get('href')elif pageCur == str(int(pageTol) - 3):print('< 上一页 ' + pageNearNum[0] + " ... " + pageNearNum[1] + " " + '\033[1;31;0m' + pageCur + " " + '\033[0m' + pageNearNum[2] + " ... " + pageTol + " 下一页 >")NextPageUrl = footPage.find('a', attrs={'class': 'pagnNext'}).get('href')PrePageUrl = footPage.find('a', attrs={'class': 'pagnPrev'}).get('href')elif pageCur == pageTol:print("< 上一页 ..."+pageNearNum[0]+" "+pageNearNum[1]+" "+pageCur)PrePageUrl = footPage.find('a',attrs={'class':'pagnPrev'}).get('href')elif pageCur != '1' and pageCur != pageTol and pageCur != '2':print('< 上一页 '+pageNearNum[0]+" ... " + pageNearNum[count-2] + " "  +'\033[1;31;0m'+pageCur+" "+ '\033[0m'+pageNearNum[count-1]+" ... "+pageTol+" 下一页 >")PrePageUrl = footPage.find('a',attrs={'class':'pagnPrev'}).get('href')#获取上一页的url地址NextPageUrl = footPage.find('a',attrs={'class':'pagnNext'}).get('href')#获取下一页的url地址print("-------------------------------------------------------------------------------------------------------------------")choose = input("如果你想进行翻页请输入Y,否则为N:\n")while choose not in ['Y','N']:choose = input("操作失败!请按照提示输入(如果你想进行翻页请输入Y,否则为N):\n")if choose == 'Y':change = input("请根据上面的页码导览输入翻页的操作:\n")while change not in ['上一页','下一页',pageNearNum[count-1],pageNearNum[count-2],pageNearNum[0]]:change = input("操作失败!请根据上面的页码导览重新输入翻页的操作,或者输入F结束翻页操作:\n")if change in ['F','f']:return Noneif change == '上一页' and PrePageUrl != None:return BeautifulSoup(getHtmlText('https://www.amazon.cn' + PrePageUrl),'lxml')elif change == '下一页' and NextPageUrl != None:return BeautifulSoup(getHtmlText('https://www.amazon.cn' + NextPageUrl),'lxml')else:return BeautifulSoup(getHtmlText('https://www.amazon.cn' + dicUN[change]),'lxml')elif choose == 'N':return None

以上代码中还有我对是否进行翻页操作的判断,我是先预存的当前网页关于翻页部分的页码以及页码的url地址,所以在后面调用的时候,我们只需要根据页码找到相应的url地址就能进行网页的跳转,这里的页码以及页码url地址我是用字典保存的,我相信你们看到这里也想到了这一点。

8.DetailInfor(detailSoup)针对某本图书的详细信息介绍,当我们点击进了一本确切的图书的时候,需要给用户展示一下图书的详细信息。在这段代码中我遇到了一些困难困扰了我很久,就是我想要查找图书信息在检查工具中能够找到,但是当我用beautifulsoup去匹配的时候却打印不出来,我同学一直在提醒我一句话:“浏览器中看到的不一定是真的能在编译器中找到的,只有在输出栏打印出来了我想要的东西,才能够在编译器中找到,因为浏览器可以解析html中的css,jquery,JavaScript,但是对于beautifulsoup,它只把那些字符当做字符串,不能实现加载。”幸运的是在同学的帮助下最终我找到了那些数据。

#针对某本图书的详细信息介绍
def DetailInfor(detailSoup):SoupTitle = detailSoup.find('div',attrs={'id':'booksTitle'})bookTitle = SoupTitle.find('h1',attrs={'class':'a-size-large a-spacing-none'}).textbookAuthor = SoupTitle.find('div',attrs={'id':'bylineInfo'}).textbookIntroduction = detailSoup.find_all('noscript')[1].textbookBorder = detailSoup.find('div',attrs={'id':'detail_bullets_id'})commentTitle = detailSoup.find('h2',attrs={'data-hook':'total-review-count'}).textcommentStar = detailSoup.find('table',attrs={'class':'a-normal a-align-middle a-spacing-base'})bookH2 = bookBorder.find('h2').textbucket2 = detailSoup.find('td', attrs={'class', 'bucket'}).prettify()context = re.sub(r'[\n| ]','', bucket2)contentSoup = BeautifulSoup(context,'lxml')bookContent = contentSoup.find_all('li')print("+------------------------------------------------------------------------------------------------------------+")print('\033[1;31;0m'+str(bookTitle).replace("\n","")+'\033[0m\n')print(str(bookAuthor).replace('\n', ''))print("\n图书介绍:",re.sub(r' {2,}', "\n", bookIntroduction))#如果出现两个及以上的空格则替换成换行符print(bookH2)for i in bookContent:print(i.text)print("\n用户评论:")print(commentTitle)review(commentStar)

9.review(commentStar)starComment(url)主要是用于分类打印出不同星级的评论,但是由于有的评论太多,所以我没有进行翻页处理,只打印当前星级评论第一页的所有评论,在这里我还是遇到了一些问题,这里我尝试了用正则表达式来匹配数据,因为不太会用正则,所以在匹配的时候真的快把自己搞到崩溃,我用的是最简单的.*?来替代一些不需要的数据,但是忽略了有些标签的数据的必要的,不能替代,所以我一直没有找到我想要的数据。。。最后还是找到了

#查看读者的评论,并得到不同星级评论对应的url
def review(commentStar):stars = commentStar.find_all('td',attrs={'class':'a-text-right aok-nowrap'})starPic = '*'starNum = 5starDic = {}for star in stars:#得到评论的等级以及url地址starA = star.find('a')if starA != None:starUrl = starA.get('href')starPercent = starA.textprint(str(starPic*starNum).ljust(9),starPercent)starDic[str(starNum)] = starUrl# print(starDic)starNum -= 1else:print(str(starPic * starNum).ljust(9), '0%')starNum -= 1print("\n")for dicKey,dicValue in starDic.items():print("\033[1;33;0m+==========================+")print("+                          +")print("+",dicKey,'星评论:                +')print("+                          +")print("+==========================+\033[0m")print("+------------------------------------------------------------------------------------------------------------+")# print(dicValue)starComment(dicValue)#得到用户评论内容
def starComment(url):rs = getHtmlText('https://www.amazon.cn/'+url)userName = re.findall(r'<span class="a-profile-name">(.*?)</span>'+r'.*?review-date">(.*?)</span>'+r'.*?current_format">(.*?)</a>' +r'.*?a-size-base review-text">(.*?)</span>', rs)for i,j,k,l in userName:print("\n昵称:"+re.sub(r'\n| ','',str(i))+"\n")print(re.sub(r'\n| ','',str(j)))print(re.sub(r'\n| ', '', str(k)) + "\n")l = re.sub(r'\n| ', '', str(l))print('评论:\n'+l.replace('<br/>','\n') + "\n")print("+------------------------------------------------------------------------------------------------------------+")

10.OutputMenu(soup)如果说前面的方法都是汽车的基础构件,那么这个方法便是汽车的引擎,有了它,前面的方法才能一起运转。代码逻辑没有什么难的,主要用于输入指令然后进行相应的回应。我也就不详细解说了,一看都会明白;

#主要的操作控制函数
def OutputMenu(soup):largeItem, items = findAllItems(soup)strType = input("请根据上面的目录输入你想要查找的书籍类型:\n")rs = findUrl(strType, largeItem, items)while (rs == None):strType = input("查找失败!请根据上面的目录重新输入你想要查找的书籍类型:\n")rs = findUrl(strType, largeItem, items)bookSoup = BeautifulSoup(rs, 'lxml')bookUrl = bookList(bookSoup)  # 列出当前页面图书列表pageTol = str(bookSoup.find('div', attrs={'class': 'pagnHy'}).find('span', attrs={'class': 'pagnDisabled'}).text)rsChoose = ChoosePage(bookSoup, pageTol)while rsChoose != None:bookUrl = bookList(rsChoose)rsChoose = ChoosePage(rsChoose, pageTol)while True:try:bookNum = eval(input("请输入你想查看的的书籍:\n"))if type(bookNum) == int and 0 < bookNum <= len(bookUrl): breakexcept NameError:print("查询错误!",end="")rs = getHtmlText(bookUrl[bookNum - 1])detailSoup = BeautifulSoup(rs,'lxml')DetailInfor(detailSoup)

11.main()
文章到了结尾,终于差不多讲完了,这是最后的main函数,希望我前面没有写错别字。。。

#主函数界面def main():url = "https://www.amazon.cn/gp/book/all_category/ref=sv_b_1"rs = getHtmlText(url)soup = BeautifulSoup(rs,'lxml')outPrinMessage(1)OutputMenu(soup)main()

运行结果展示


尾声

我也不知道还要说什么,虽然自己的python编码能力不是很好,但是还是会不断学习,BeautifulSoup在这里是用的最多的,用法也不算难,只是要真正理解到它的作用以及含义,在此之前我承认我的确含含糊糊的,现在也不能说完全理解,但是我会花时间去慢慢了解它。第一次写这么长的博客。。。不说读者会看的不耐烦,我自己也觉得写得不耐烦了,哈哈哈。

Python基于BeautifulSoup4库爬取亚马逊网页相关推荐

  1. Python实现通过ASIN爬取亚马逊产品评论

    Python实现通过ASIN爬取亚马逊产品评论 一.最近一直在研究爬取亚马逊评论相关的信息,亚马逊的反爬机制还是比较严格的,时不时就封cookie啊封ip啊啥的.而且他们的网页排版相对没有那么规则,所 ...

  2. python学习 爬取亚马逊网页,失败后。修改HTTP报文头部后成功!

    通过修改HTTP报文头部,来成功获取网页内容! python import requests r = requests.get("https://www.amazon.cn/gp/produ ...

  3. python爬取网页书籍名称代码_python爬取亚马逊书籍信息代码分享

    我有个需求就是抓取一些简单的书籍信息存储到mysql数据库,例如,封面图片,书名,类型,作者,简历,出版社,语种. 我比较之后,决定在亚马逊来实现我的需求. 我分析网站后发现,亚马逊有个高级搜索的功能 ...

  4. 爬虫(一):用python爬取亚马逊所有家具种类前100名的商品信息(上)

    目标 亚马逊公司(Amazon),是美国最大的一家网络电子商务公司,位于华盛顿州的西雅图,是网络上最早开始经营电子商务的公司之一,现在已成为全球商品品种最多的网上零售商和全球第二大互联网企业. 本次目 ...

  5. 爬虫(二):用python爬取亚马逊所有家具种类前100名的商品信息(下)

    目标 亚马逊公司(Amazon),是美国最大的一家网络电子商务公司,位于华盛顿州的西雅图,是网络上最早开始经营电子商务的公司之一,现在已成为全球商品品种最多的网上零售商和全球第二大互联网企业. 本次目 ...

  6. JAVA爬取亚马逊的商品信息

    在程序里面输入你想爬取的商品名字,就可以返回这件商品在亚马逊搜索中都所有相关商品的信息,包括名字和价格. 解决了在爬取亚马逊时候,亚马逊可以识别出你的爬虫,并返回503,造成只能爬取几个页面的问题. ...

  7. 爬取亚马逊评论_如何利用插件抓取亚马逊评论和关键词?

    如何抓取亚马逊的商品评价? 原本想给大家介绍使用市面上常见或者付费的爬虫工具,直到我发现了这个Chrome的免费插件 --Instant Data Scraper,当时我差点被感动哭了.比起学编程语言 ...

  8. scrapy_redis分布式爬虫爬取亚马逊图书

    scrapy_redis分布式爬虫爬取亚马逊图书 最近在学习分布式爬虫,选取当当图书进行了一次小练习 网址,https://www.amazon.cn/gp/book/all_category/ref ...

  9. python爬虫|爬取亚马逊商品库存数据(Selenium实战)

    前言 很多人把selenium爬虫称之为可视化爬虫,之所以这样认为,主要在于selenium爬虫主要是模拟人的点击操作,而selenium驱动浏览器并进行操作的过程是可以观察到的.换言之,就是你在看着 ...

最新文章

  1. H5进阶篇--实现微信摇一摇功能
  2. linux视音频解码教程,音视频编解码:NVIDIA Jetson Linux Multimedia API(总结)
  3. 【进程】进程通信-信号方式(中断)
  4. python使用协程实现udp_python-socket和进程线程协程(代码展示)
  5. Php刷新重载id,php 使用 __call重载
  6. 2.5 不匹配数据划分的偏差和方差
  7. Eclipse启动Tomcat,45S超时问题解决
  8. Vue2.0入门系列——父子组件间通信
  9. 测试网站的url脚本测试网站是否正常
  10. DAY16-Django之model
  11. NOIP2013提高组华容道题解
  12. 360系统修复过程中卡慢问题的解决方案
  13. JPG图片转换成Word文字教程分享
  14. 整车EMC正向开发及仿真
  15. 大数据Hadoop之——数据同步工具DataX
  16. 苏轼一生最智慧的20首诗词,不读懂不足以谈人生
  17. python输出被五整除的数_Python程序打印给定数字的所有被3和5整除的数字
  18. Occlusion Culling 遮挡剔除 相机系列5
  19. 无人机利用视觉slam实现位置估计
  20. Docker学习01---狂神说

热门文章

  1. python做地图导航_【python】地图做图问题
  2. 物联网区块链有望成新一轮颠覆性技术
  3. 【数据挖掘面经】腾讯+百度+华为(均拿到sp offer)
  4. 【设计模式系列24】GoF23种设计模式总结及软件设计7大原则
  5. Flutter使用UDP
  6. 2022最新Java高级程序员架构师面试题及答案
  7. cad2017怎么改变选择方式_CAD2017怎么设置经典模式,小新?
  8. 2019华为软件精英挑战赛赛后总结
  9. Xposed模块深度美化Android
  10. MT6572的所有版本对语音解锁和语音控制功能的支持情况