刚刚学完爬虫的基本知识,也基本会用request、bs4和re这三个库了,于是尝试爬取当当网商品搜索页面,这是本人第一次爬虫。
这次的爬取目标是获取搜索页面的所有商品价格和名称,所以我们对爬下来的HTML文本做了些许分析。
搜索关键词假设是“六年级”,那么与第一个商品有关的HTML便如下(用了YAML代码块来表示,请见谅)。可以发现,与第一个商品有关的名称位于名称为p、属性为name的标签下,而价格则位于名称为p、属性为price的标签下。值得注意的是,这两个标签之间还隔着一个名称为p、属性为detail的标签,而且这三个标签一并构成了平行标签
为了解析html更方便,在找到名称为p、属性为name的标签之后,直接用next_sibling访问下一个平行标签。用正则表达式匹配商品价格和名称之后,存入键值对之中,并打印到txt文件里。
<p class="name" name="title">
<a dd_name="单品标题" ddclick="act=normalResult_title&pos=20916683_0_1_q" href="http://product.dangdang.com/20916683.html" name="itemlist-title" target="_blank" title=" 六年级英语阅读理解与完型填空加油站 ">
<font class="skcolor_ljg">
六年级
</font>
英语阅读理解与完型填空加油站
</a>
</p>
<p class="detail">
</p>
<p class="price">
<span class="search_now_price">
¥19.80
</span>
<a class="search_discount" style="text-decoration:none;">
定价:
</a>
<span class="search_pre_price">
¥22.00
</span>
<span class="search_discount">
(9折)
</span>
</p>
全代码如下(这里只能爬取搜索结果第一页):
import requests
import re
from bs4 import BeautifulSoup
def getHTMLtext(url):
try:
r = requests.get(url, timeout=30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return "ERROR"
def parseHTML(html):
dict = {}
pat_title = re.compile(r'title=\".*?\"')
pat_price = re.compile(r'¥\d*[.]\d{2}')
soup = BeautifulSoup(html, 'html.parser')
for tag in soup.find_all('p', 'name'):
try:
t = pat_title.search(str(tag)).group(0).split("\"")[1]
p = pat_price.search(str(tag.next_sibling.next_sibling)).group(0)
dict[t] = p
except:
continue
return dict
def main():
key = "C++"
url = "http://search.dangdang.com/?key=" + key
html = getHTMLtext(url)
dict = parseHTML(html)
path = "D:\\当当网爬取结果(" + key + ").txt"
tplt = "{:4}\t{:8}\t{:16}"
with open(path, "w", encoding="utf-8") as f:
count = 0
f.write(tplt.format("序号","价格","商品名称")+"\n")
for d in dict.items():
count += 1
f.write(tplt.format(count, d[1], d[0])+"\n")
main()
输出结果如下:
第一次做爬虫,而且也是刚刚上手python,可能还有许多待优化的地方。
完(๑′ᴗ‵๑)