<\/pre>請(qǐng)注意以上兩個(gè)屬性獲取的都是直接<\/strong>子節(jié)點(diǎn),例如 h2<\/code> 標(biāo)簽內(nèi)的后代標(biāo)簽 span<\/code> ,不會(huì)單獨(dú)獲取到。<\/p>如果希望將所有的標(biāo)簽都獲取到,使用 descendants<\/code> 屬性,它返回的是一個(gè)生成器,所有標(biāo)簽包括標(biāo)簽內(nèi)的文本都會(huì)單獨(dú)獲取。<\/p>print(list(soup.div.descendants))<\/pre>其它節(jié)點(diǎn)的獲取(了解即可,即查即用)<\/p>
parent<\/code> 和 parents<\/code>:直接父節(jié)點(diǎn)和所有父節(jié)點(diǎn);<\/p><\/li>next_sibling<\/code>,next_siblings<\/code>,previous_sibling<\/code>,previous_siblings<\/code>:分別表示下一個(gè)兄弟節(jié)點(diǎn)、下面所有兄弟節(jié)點(diǎn)、上一個(gè)兄弟節(jié)點(diǎn)、上面所有兄弟節(jié)點(diǎn),由于換行符也是一個(gè)節(jié)點(diǎn),所有在使用這幾個(gè)屬性時(shí),要注意一下?lián)Q行符;<\/p><\/li>next_element<\/code>,next_elements<\/code>,previous_element<\/code>,previous_elements<\/code>:這幾個(gè)屬性分別表示上一個(gè)節(jié)點(diǎn)或者下一個(gè)節(jié)點(diǎn),注意它們不分層次,而是針對(duì)所有節(jié)點(diǎn),例如上述代碼中 div<\/code> 節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)是 h2<\/code>,而 div<\/code> 節(jié)點(diǎn)的兄弟節(jié)點(diǎn)是 ul<\/code>。<\/p><\/li><\/ul>文檔樹(shù)搜索相關(guān)函數(shù)<\/strong><\/p>第一個(gè)要學(xué)習(xí)的函數(shù)就是 find_all()<\/code> 函數(shù),原型如下所示:<\/strong><\/p>find_all(name,attrs,recursive,text,limit=None,**kwargs)<\/pre>
name<\/code>:該參數(shù)為 tag 標(biāo)簽的名字,例如 find_all('p')<\/code> 是查找所有的 p<\/code><\/p>La commande d'installation de la bibliothèque est la suivante?:<\/strong>#????#print(soup.find_all('li')) # 獲取所有的 li\nprint(soup.find_all(attrs={'class': 'nav'})) # 傳入 attrs 屬性\nprint(soup.find_all(re.compile(\"p\"))) # 傳遞正則,實(shí)測(cè)效果不理想\nprint(soup.find_all(['a','p'])) # 傳遞列表<\/pre>#????#BeautifulSoup<\/code> Lors de l'analyse des données, vous devez s'appuyer sur des analyseurs tiers,les analyseurs couramment utilisés et leurs avantages sont les suivants?:<\/strong>#????#- #????#
analyseur standard python html.<\/code>?: bibliothèque standard intégrée python, forte tolérance aux pannes?; #????#<\/li>- #????#
analyseur lxml<\/code>?: rapide, puissant?; tolérance aux pannes?; #?? ??#<\/li>- #????#
html5lib<\/code>?: la plus tolérante aux pannes et la méthode d'analyse est cohérente avec le navigateur. #????#<\/li><\/ul>#????# Ensuite, utilisez un code HTML personnalisé pour démontrer l'utilisation de base de la bibliothèque beautifulsoup4<\/code> Le code de test est le suivant?: #????. #print(soup.body.div.find_all(['a','p'],recursive=False)) # 傳遞列表<\/pre># ????#Utilisez BeautifulSoup<\/code> pour effectuer des opérations simples dessus, notamment l'instanciation d'objets BS, la sortie de balises de page, etc. #????#print(soup.find_all(text='首頁(yè)')) # ['首頁(yè)']\nprint(soup.find_all(text=re.compile(\"^首\"))) # ['首頁(yè)']\nprint(soup.find_all(text=[\"首頁(yè)\",re.compile('課')])) # ['橡皮擦的爬蟲(chóng)課', '首頁(yè)', '專(zhuān)欄課程']<\/pre>#????#Nous pouvons appeler directement la balise de page Web via l'objet BeautifulSoup. Il y a un problème ici. L'appel de la balise via l'objet BS ne peut que classer la balise en premier. la balise en première position est obtenue. Une balise p<\/code>, si vous souhaitez obtenir plus de contenu, veuillez continuer à lire. #????##????#Après avoir appris cela, nous devons comprendre les 4 objets intégrés dans BeautifulSoup?:<\/strong>#????#- # ????#
BeautifulSoup<\/code>?: Objet de base, l'objet HTML entier, généralement considéré comme un objet Tag?; #????#<\/li>- #????#
Tag<\/?; code> : Objet Label, l'étiquette est chaque n?ud de la page Web, tel que title, head, p; #????#<\/li>- #????#
NavigableString<\/code>?: Label internal string; #?? ??#<\/li>- #????#
Comment<\/code>?: Objet de commentaire, il n'y a pas beaucoup de scénarios d'utilisation dans les robots. #????#<\/li><\/ul>#????#Le code suivant vous montre les scénarios dans lesquels ces objets apparaissent. Faites attention aux commentaires pertinents dans le code?: <\/strong>#????#. print(soup.find_all(class_ = 'nav'))\nprint(soup.find_all(class_ = 'nav li'))<\/pre># ????#Pour l'objet Tag<\/strong>, il existe deux attributs importants, qui sont name<\/code> et attrs<\/code><\/strong>#?? ??# print(soup.select('ul[class^=\"na\"]'))<\/pre>#????#Le code ci-dessus démontre l'utilisation de l'obtention de l'attribut name<\/code> et de l'attribut attrs<\/code>. L'attribut attrs<\/code> obtient un dictionnaire. , qui peut être transmis Key obtient la valeur correspondante. #????##????#Obtenir la valeur d'attribut de la balise Dans BeautifulSoup, vous pouvez également utiliser la méthode suivante : #????#print(soup.select('ul[class*=\"li\"]'))<\/pre>#????#Obtenir l'objet NavigableString<\/code>< \/strong> Après avoir obtenu la balise de page Web, vous devez obtenir le texte contenu dans la balise, ce qui se fait via le code suivant. #????#from bs4 import BeautifulSoup\nimport requests\nimport logging\nlogging.basicConfig(level=logging.NOTSET)\ndef get_html(url, headers) -> None:\n try:\n res = requests.get(url=url, headers=headers, timeout=3)\n except Exception as e:\n logging.debug(\"采集異常\", e)\n\n if res is not None:\n html_str = res.text\n soup = BeautifulSoup(html_str, \"html.parser\")\n imgs = soup.find_all(attrs={'class': 'lazy'})\n print(\"獲取到的數(shù)據(jù)量是\", len(imgs))\n datas = []\n for item in imgs:\n name = item.get('alt')\n src = item[\"src\"]\n logging.info(f\"{name},{src}\")\n # 獲取拼接數(shù)據(jù)\n datas.append((name, src))\n save(datas, headers)\ndef save(datas, headers) -> None:\n if datas is not None:\n for item in datas:\n try:\n # 抓取圖片\n res = requests.get(url=item[1], headers=headers, timeout=5)\n except Exception as e:\n logging.debug(e)\n\n if res is not None:\n img_data = res.content\n with open(\".\/imgs\/{}.jpg\".format(item[0]), \"wb+\") as f:\n f.write(img_data)\n else:\n return None\nif __name__ == '__main__':\n headers = {\n \"User-Agent\": \"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/93.0.4577.82 Safari\/537.36\"\n }\n url_format = \"http:\/\/www.9thws.com\/#p{}\"\n urls = [url_format.format(i) for i in range(1, 2)]\n get_html(urls[0], headers)<\/pre>#????#De plus, vous pouvez également utiliser l'attribut text<\/code> et la méthode get_text()<\/code> pour obtenir le contenu de la balise. #????#rrreee#????# Vous pouvez également obtenir tout le texte de la balise en utilisant strings<\/code> et stripped_strings<\/code>. #????#rrreee#????#Sélecteur de balise\/n?ud étendu traversant l'arborescence du document<\/strong>#????##????#N?ud enfant direct#????##????#Objet Tag Les éléments enfants directs peut être obtenu en utilisant les attributs contents<\/code> et children<\/code>. #????#rrreee#????#Veuillez noter que les deux attributs ci-dessus obtiennent les n?uds enfants directs<\/strong>, tels que la balise descendante span<\/ dans le h2<\/code> code de balise> ne sera pas obtenu séparément. #????##????#Si vous souhaitez obtenir toutes les balises, utilisez l'attribut descendants<\/code>. Il renvoie un générateur et toutes les balises, y compris le texte à l'intérieur des balises, seront récupérées séparément. #????#rrreee#????#Acquisition d'autres n?uds (il suffit de comprendre, vérifier et utiliser) #????#- #????#
parent <\/ code> et parents<\/code>?: n?ud parent direct et tous les n?uds parents?; #????#<\/li>- #????#
next_sibling<\/code>, next_siblings <\/ code>, previous_sibling<\/code>, previous_siblings<\/code>?: représentent respectivement le n?ud frère suivant, tous les n?uds frères en dessous, le n?ud frère précédent et tous les n?uds frères au-dessus puisque le caractère de nouvelle ligne est également. un n?ud, lorsque vous utilisez ces attributs, veuillez faire attention au saut de ligne #????#<\/li>- #????#
next_element<\/code>, next_elements<\/code>, < code>previous_element<\/code>, previous_elements<\/code>?: ces attributs représentent respectivement le n?ud précédent ou le n?ud suivant. Notez qu'ils ne sont pas hiérarchiques, mais ciblent tous les n?uds, comme dans le code ci-dessus div<\/code> est h2<\/code>, et le n?ud frère du n?ud div<\/code> est ul<\/code>. #????#<\/li><\/ul>#????#Fonctions liées à la recherche dans l'arborescence des documents<\/strong>#????##????#La première fonction à apprendre est find_all() <\/ code>, le prototype est le suivant : <\/strong>#????#rrreee- #????#
name<\/code> : Ce paramètre est le nom de la balise. Par exemple, find_all('p')<\/code> sert à rechercher toutes les balises p<\/code>. Il peut accepter les cha?nes de nom de balise, les expressions régulières et. listes #????#<\/li>attrs<\/code>:傳入的屬性,該參數(shù)可以字典的形式傳入,例如 attrs={'class': 'nav'}<\/code>,返回的結(jié)果是 tag 類(lèi)型的列表;<\/p><\/li><\/ul>上述兩個(gè)參數(shù)的用法示例如下:<\/strong><\/p>print(soup.find_all('li')) # 獲取所有的 li\nprint(soup.find_all(attrs={'class': 'nav'})) # 傳入 attrs 屬性\nprint(soup.find_all(re.compile(\"p\"))) # 傳遞正則,實(shí)測(cè)效果不理想\nprint(soup.find_all(['a','p'])) # 傳遞列表<\/pre>
recursive<\/code>:調(diào)用 find_all ()<\/code> 方法時(shí),BeautifulSoup 會(huì)檢索當(dāng)前 tag 的所有子孫節(jié)點(diǎn),如果只想搜索 tag 的直接子節(jié)點(diǎn),可以使用參數(shù) recursive=False<\/code>,測(cè)試代碼如下:<\/p><\/li><\/ul>print(soup.body.div.find_all(['a','p'],recursive=False)) # 傳遞列表<\/pre>
text<\/code>:可以檢索文檔中的文本字符串內(nèi)容,與 name<\/code> 參數(shù)的可選值一樣,text<\/code> 參數(shù)接受標(biāo)簽名字符串、正則表達(dá)式、 列表;<\/p><\/li><\/ul>print(soup.find_all(text='首頁(yè)')) # ['首頁(yè)']\nprint(soup.find_all(text=re.compile(\"^首\"))) # ['首頁(yè)']\nprint(soup.find_all(text=[\"首頁(yè)\",re.compile('課')])) # ['橡皮擦的爬蟲(chóng)課', '首頁(yè)', '專(zhuān)欄課程']<\/pre>
limit<\/code>:可以用來(lái)限制返回結(jié)果的數(shù)量;<\/p><\/li>kwargs<\/code>:如果一個(gè)指定名字的參數(shù)不是搜索內(nèi)置的參數(shù)名,搜索時(shí)會(huì)把該參數(shù)當(dāng)作 tag 的屬性來(lái)搜索。這里要按 class<\/code> 屬性搜索,因?yàn)?nbsp;class<\/code> 是 python 的保留字,需要寫(xiě)作 class_<\/code>,按 class_<\/code> 查找時(shí),只要一個(gè) CSS 類(lèi)名滿(mǎn)足即可,如需多個(gè) CSS 名稱(chēng),填寫(xiě)順序需要與標(biāo)簽一致。<\/p><\/li><\/ul>print(soup.find_all(class_ = 'nav'))\nprint(soup.find_all(class_ = 'nav li'))<\/pre>還需要注意網(wǎng)頁(yè)節(jié)點(diǎn)中,有些屬性在搜索中不能作為kwargs<\/code>參數(shù)使用,比如html5<\/code> 中的 data-*<\/code>屬性,需要通過(guò)attrs<\/code>參數(shù)進(jìn)行匹配。<\/p>與 find_all()<\/code>方法用戶(hù)基本一致的其它方法清單如下:<\/p><\/blockquote>find()<\/code>:函數(shù)原型find( name , attrs , recursive , text , **kwargs )<\/code>,返回一個(gè)匹配元素;<\/p><\/li>find_parents(),find_parent()<\/code>:函數(shù)原型 find_parent(self, name=None, attrs={}, **kwargs)<\/code>,返回當(dāng)前節(jié)點(diǎn)的父級(jí)節(jié)點(diǎn);<\/p><\/li>find_next_siblings(),find_next_sibling()<\/code>:函數(shù)原型 find_next_sibling(self, name=None, attrs={}, text=None, **kwargs)<\/code>,返回當(dāng)前節(jié)點(diǎn)的下一兄弟節(jié)點(diǎn);<\/p><\/li>find_previous_siblings(),find_previous_sibling()<\/code>:同上,返回當(dāng)前的節(jié)點(diǎn)的上一兄弟節(jié)點(diǎn);<\/p><\/li>find_all_next(),find_next(),find_all_previous () ,find_previous ()<\/code>:函數(shù)原型 find_all_next(self, name=None, attrs={}, text=None, limit=None, **kwargs)<\/code>,檢索當(dāng)前節(jié)點(diǎn)的后代節(jié)點(diǎn)。<\/p><\/li><\/ul>CSS 選擇器<\/strong> 該小節(jié)的知識(shí)點(diǎn)與pyquery<\/code>有點(diǎn)撞車(chē),核心使用select()<\/code>方法即可實(shí)現(xiàn),返回?cái)?shù)據(jù)是列表元組。<\/p>