过程分析
参考:https://mp.weixin.qq.com/s/ET9HP2n3905PxBy4ZLmZNw
首先是书籍排行榜的地址:
http://bang.dangdang.com/books/fivestars/01.00.00.00.00.00-recent30-0-0-1-1
我们要的就是前 500 本书的:排名,书名,图片地址,作者,推荐指数,五星评分次数,价格
查看源码,可以得到这些信息放在<li>
标签中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <li> <div class="list_num red">2.</div> <div class="pic"><a href="http://product.dangdang.com/25197810.html" target="_blank"><img src="http://img3m0.ddimg.cn/33/33/25197810-1_l_3.jpg" alt="尤尔小屋的猫" title="尤尔小屋的猫"></a></div> <div class="name"><a href="http://product.dangdang.com/25197810.html" target="_blank" title="尤尔小屋的猫">尤尔小屋的猫</a></div> <div class="star"><span class="level"><span style="width: 96.4%;"></span></span><a href="http://product.dangdang.com/25197810.html?point=comment_point" target="_blank">138068条评论</a><span class="tuijian">100%推荐</span></div> <div class="publisher_info"><a href="http://search.dangdang.com/?key=莉莉·海沃德" title="莉莉·海沃德、译者张玫瑰,酷威文化 出品" target="_blank">莉莉·海沃德</a>、<a href="http://search.dangdang.com/?key=译者张玫瑰" title="莉莉·海沃德、译者张玫瑰,酷威文化 出品" target="_blank">译者张玫瑰</a>,<a href="http://search.dangdang.com/?key=酷威文化" title="莉莉·海沃德、译者张玫瑰,酷威文化 出品" target="_blank">酷威文化</a> 出品</div> <div class="publisher_info"><span>2018-01-01</span> <a href="http://search.dangdang.com/?key=百花洲文艺出版社" target="_blank">百花洲文艺出版社</a></div> <div class="biaosheng">五星评分:<span>65923次</span></div> <div class="price"> <p><span class="price_n">¥31.30</span> <span class="price_r">¥39.80</span>(<span class="price_s">7.9折</span>) </p> <p class="price_e"></p> <div class="buy_button"> <a ddname="加入购物车" name="" href="javascript:AddToShoppingCart('25197810');" class="listbtn_buy">加入购物车</a> <a ddname="加入收藏" id="addto_favorlist_25197810" name="" href="javascript:showMsgBox('addto_favorlist_25197810',encodeURIComponent('25197810&platform=3'), 'http://myhome.dangdang.com/addFavoritepop');" class="listbtn_collect">收藏</a> </div> </div> </li>
首先是主函数:
用page实现翻页,使用 requests 请求当当网,然后将返回的 HTML 进行正则解析,最后保存到txt文件里
1 2 3 4 5 6 7 8 9 10 def main (page ): url = 'http://bang.dangdang.com/books/fivestars/01.00.00.00.00.00-recent30-0-0-1-' + str(page) html = request_dandan(url) items = parse_result(html) for item in items: write_item_to_file(item) if __name__ == "__main__" : for i in range(1 , 26 ): main(i)
然后逐个实现各个函数:
1 2 3 4 5 6 7 def request_dandan (url ): try : response = requests.get(url) if response.status_code == 200 : return response.text except requests.RequestException: return None
这里调用了requests模块向服务器发送get请求,get请求去指定的url获取网页数据,随后对响应码作了判断,200代表获取成功,成功就返回获取的响应数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def parse_result (html ): pattern = re.compile( '<li>.*?list_num.*?(\d+).</div>.*?<img src="(.*?)".*?class="name".*?title="(.*?)">.*?class="star">.*?class="tuijian">(.*?)</span>.*?class="publisher_info">.*?target="_blank">(.*?)</a>.*?class="biaosheng">.*?<span>(.*?)</span></div>.*?<p><span\sclass="price_n">¥(.*?)</span>.*?</li>' , re.S) items = re.findall(pattern, html) for item in items: yield { 'range' : item[0 ], 'iamge' : item[1 ], 'title' : item[2 ], 'recommend' : item[3 ], 'author' : item[4 ], 'times' : item[5 ], 'price' : item[6 ] }
这里使用compile对正则表达式进行封装,并用findall查找所用匹配项
yield 的用法可以参考:
来具体看一看正则表达式:
1 <li>.*?list_num.*?(\d+).</div>
这一句匹配的是
1 2 <li> <div class="list_num red">1.</div>
注意,\d+
被括号括起来了,代表将匹配的这部分内容(即图中的1这个数字)捕获并作为1个元素存放到了一个数组中,所以现在匹配结果对应的数组中(即item)第一个元素是1,也就是排名。
剩下的正则表达式类似,就不多讲了
最后写入文件:
1 2 3 4 def write_item_to_file (item ): print('开始写入数据 ====> ' + str(item)) with open('book.txt' , 'a' , encoding='UTF-8' ) as f: f.write(json.dumps(item, ensure_ascii=False ) + '\n' )
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 import requestsimport reimport jsondef request_dandan (url ): try : response = requests.get(url) if response.status_code == 200 : return response.text except requests.RequestException: return None def parse_result (html ): pattern = re.compile( '<li>.*?list_num.*?(\d+).</div>.*?<img src="(.*?)".*?class="name".*?title="(.*?)">.*?class="star">.*?class="tuijian">(.*?)</span>.*?class="publisher_info">.*?target="_blank">(.*?)</a>.*?class="biaosheng">.*?<span>(.*?)</span></div>.*?<p><span\sclass="price_n">¥(.*?)</span>.*?</li>' , re.S) items = re.findall(pattern, html) for item in items: yield { 'range' : item[0 ], 'iamge' : item[1 ], 'title' : item[2 ], 'recommend' : item[3 ], 'author' : item[4 ], 'times' : item[5 ], 'price' : item[6 ] } def write_item_to_file (item ): print('开始写入数据 ====> ' + str(item)) with open('book.txt' , 'a' , encoding='UTF-8' ) as f: f.write(json.dumps(item, ensure_ascii=False ) + '\n' ) def main (page ): url = 'http://bang.dangdang.com/books/fivestars/01.00.00.00.00.00-recent30-0-0-1-' + str(page) html = request_dandan(url) items = parse_result(html) for item in items: write_item_to_file(item) if __name__ == "__main__" : for i in range(1 , 26 ): main(i)